summaryrefslogtreecommitdiff
path: root/boost
diff options
context:
space:
mode:
Diffstat (limited to 'boost')
-rw-r--r--boost/accumulators/numeric/functional.hpp52
-rw-r--r--boost/accumulators/numeric/functional/valarray.hpp68
-rw-r--r--boost/accumulators/numeric/functional/vector.hpp34
-rw-r--r--boost/accumulators/statistics/covariance.hpp12
-rw-r--r--boost/accumulators/statistics/tail.hpp5
-rw-r--r--boost/accumulators/statistics/tail_variate_means.hpp4
-rw-r--r--boost/accumulators/statistics/times2_iterator.hpp8
-rw-r--r--boost/accumulators/statistics/weighted_tail_variate_means.hpp4
-rw-r--r--boost/algorithm/cxx11/is_partitioned.hpp6
-rw-r--r--boost/algorithm/cxx14/equal.hpp3
-rw-r--r--boost/algorithm/cxx17/exclusive_scan.hpp52
-rw-r--r--boost/algorithm/cxx17/for_each_n.hpp37
-rw-r--r--boost/algorithm/cxx17/inclusive_scan.hpp60
-rw-r--r--boost/algorithm/cxx17/reduce.hpp72
-rw-r--r--boost/algorithm/cxx17/transform_exclusive_scan.hpp46
-rw-r--r--boost/algorithm/cxx17/transform_inclusive_scan.hpp58
-rw-r--r--boost/algorithm/cxx17/transform_reduce.hpp55
-rw-r--r--boost/algorithm/hex.hpp2
-rw-r--r--boost/algorithm/is_palindrome.hpp29
-rw-r--r--boost/algorithm/is_partitioned_until.hpp63
-rw-r--r--boost/algorithm/searching/boyer_moore.hpp16
-rw-r--r--boost/algorithm/searching/knuth_morris_pratt.hpp6
-rw-r--r--boost/algorithm/string/detail/case_conv.hpp8
-rw-r--r--boost/algorithm/string/detail/find_iterator.hpp2
-rw-r--r--boost/algorithm/string/detail/util.hpp5
-rw-r--r--boost/align/aligned_allocator.hpp6
-rw-r--r--boost/align/aligned_allocator_adaptor.hpp47
-rw-r--r--boost/align/detail/align.hpp4
-rw-r--r--boost/align/detail/align_down.hpp4
-rw-r--r--boost/align/detail/align_up.hpp4
-rw-r--r--boost/align/detail/alignment_of_msvc.hpp3
-rw-r--r--boost/align/detail/is_alignment.hpp1
-rw-r--r--boost/archive/basic_text_iarchive.hpp2
-rw-r--r--boost/archive/codecvt_null.hpp13
-rw-r--r--boost/archive/detail/iserializer.hpp2
-rw-r--r--boost/archive/impl/archive_serializer_map.ipp4
-rw-r--r--boost/archive/impl/basic_binary_iprimitive.ipp4
-rw-r--r--boost/archive/impl/basic_binary_oprimitive.ipp2
-rw-r--r--boost/archive/impl/text_wiarchive_impl.ipp2
-rw-r--r--boost/archive/impl/xml_woarchive_impl.ipp2
-rw-r--r--boost/archive/iterators/base64_from_binary.hpp2
-rw-r--r--boost/archive/iterators/binary_from_base64.hpp2
-rw-r--r--boost/archive/iterators/escape.hpp3
-rw-r--r--boost/archive/iterators/istream_iterator.hpp6
-rw-r--r--boost/archive/iterators/mb_from_wchar.hpp3
-rw-r--r--boost/archive/iterators/transform_width.hpp1
-rw-r--r--boost/archive/iterators/wchar_from_mb.hpp2
-rw-r--r--boost/archive/wcslen.hpp2
-rw-r--r--boost/asio/detail/config.hpp21
-rw-r--r--boost/asio/detail/dev_poll_reactor.hpp12
-rw-r--r--boost/asio/detail/epoll_reactor.hpp13
-rw-r--r--boost/asio/detail/impl/dev_poll_reactor.ipp5
-rw-r--r--boost/asio/detail/impl/epoll_reactor.ipp39
-rw-r--r--boost/asio/detail/impl/kqueue_reactor.ipp28
-rw-r--r--boost/asio/detail/impl/reactive_descriptor_service.ipp19
-rw-r--r--boost/asio/detail/impl/reactive_socket_service_base.ipp14
-rw-r--r--boost/asio/detail/impl/select_reactor.ipp5
-rw-r--r--boost/asio/detail/impl/signal_set_service.ipp6
-rw-r--r--boost/asio/detail/impl/win_iocp_socket_service_base.ipp19
-rw-r--r--boost/asio/detail/kqueue_reactor.hpp12
-rw-r--r--boost/asio/detail/op_queue.hpp6
-rw-r--r--boost/asio/detail/select_reactor.hpp13
-rw-r--r--boost/asio/detail/socket_types.hpp6
-rw-r--r--boost/asio/detail/winapi_thread.hpp6
-rw-r--r--boost/asio/use_future.hpp6
-rw-r--r--boost/asio/version.hpp2
-rw-r--r--boost/atomic/detail/atomic_template.hpp435
-rw-r--r--boost/atomic/detail/bitwise_cast.hpp12
-rw-r--r--boost/atomic/detail/config.hpp26
-rw-r--r--boost/atomic/detail/ops_emulated.hpp5
-rw-r--r--boost/atomic/detail/ops_gcc_alpha.hpp10
-rw-r--r--boost/atomic/detail/ops_gcc_arm.hpp10
-rw-r--r--boost/atomic/detail/ops_gcc_atomic.hpp5
-rw-r--r--boost/atomic/detail/ops_gcc_ppc.hpp10
-rw-r--r--boost/atomic/detail/ops_gcc_sparc.hpp10
-rw-r--r--boost/atomic/detail/ops_gcc_sync.hpp5
-rw-r--r--boost/atomic/detail/ops_gcc_x86.hpp5
-rw-r--r--boost/atomic/detail/ops_gcc_x86_dcas.hpp10
-rw-r--r--boost/atomic/detail/ops_linux_arm.hpp5
-rw-r--r--boost/atomic/detail/ops_msvc_arm.hpp9
-rw-r--r--boost/atomic/detail/ops_msvc_x86.hpp19
-rw-r--r--boost/atomic/detail/ops_windows.hpp9
-rw-r--r--boost/atomic/detail/platform.hpp3
-rw-r--r--boost/atomic/detail/storage_type.hpp48
-rw-r--r--boost/atomic/detail/type_traits/conditional.hpp42
-rw-r--r--boost/atomic/detail/type_traits/is_function.hpp42
-rw-r--r--boost/atomic/detail/type_traits/is_integral.hpp43
-rw-r--r--boost/atomic/detail/type_traits/is_signed.hpp43
-rw-r--r--boost/atomic/detail/type_traits/make_signed.hpp43
-rw-r--r--boost/chrono/duration.hpp58
-rw-r--r--boost/chrono/io/duration_io.hpp2
-rw-r--r--boost/chrono/io/time_point_io.hpp18
-rw-r--r--boost/chrono/io/time_point_units.hpp2
-rw-r--r--boost/chrono/process_cpu_clocks.hpp4
-rw-r--r--boost/chrono/time_point.hpp1
-rw-r--r--boost/circular_buffer/base.hpp18
-rw-r--r--boost/circular_buffer/details.hpp20
-rw-r--r--boost/compute/algorithm/accumulate.hpp4
-rw-r--r--boost/compute/algorithm/adjacent_difference.hpp3
-rw-r--r--boost/compute/algorithm/adjacent_find.hpp2
-rw-r--r--boost/compute/algorithm/all_of.hpp2
-rw-r--r--boost/compute/algorithm/any_of.hpp2
-rw-r--r--boost/compute/algorithm/binary_search.hpp2
-rw-r--r--boost/compute/algorithm/copy.hpp2
-rw-r--r--boost/compute/algorithm/copy_if.hpp2
-rw-r--r--boost/compute/algorithm/copy_n.hpp2
-rw-r--r--boost/compute/algorithm/count.hpp3
-rw-r--r--boost/compute/algorithm/count_if.hpp3
-rw-r--r--boost/compute/algorithm/detail/copy_on_device.hpp4
-rw-r--r--boost/compute/algorithm/detail/copy_to_device.hpp4
-rw-r--r--boost/compute/algorithm/detail/copy_to_host.hpp4
-rw-r--r--boost/compute/algorithm/detail/find_extrema.hpp2
-rw-r--r--boost/compute/algorithm/detail/find_extrema_with_reduce.hpp1
-rw-r--r--boost/compute/algorithm/detail/find_if_with_atomics.hpp1
-rw-r--r--boost/compute/algorithm/detail/merge_sort_on_gpu.hpp10
-rw-r--r--boost/compute/algorithm/detail/radix_sort.hpp8
-rw-r--r--boost/compute/algorithm/detail/serial_reduce.hpp1
-rw-r--r--boost/compute/algorithm/detail/serial_reduce_by_key.hpp6
-rw-r--r--boost/compute/algorithm/equal.hpp2
-rw-r--r--boost/compute/algorithm/equal_range.hpp2
-rw-r--r--boost/compute/algorithm/exclusive_scan.hpp4
-rw-r--r--boost/compute/algorithm/fill.hpp10
-rw-r--r--boost/compute/algorithm/fill_n.hpp2
-rw-r--r--boost/compute/algorithm/find.hpp2
-rw-r--r--boost/compute/algorithm/find_end.hpp6
-rw-r--r--boost/compute/algorithm/find_if.hpp2
-rw-r--r--boost/compute/algorithm/find_if_not.hpp2
-rw-r--r--boost/compute/algorithm/for_each.hpp2
-rw-r--r--boost/compute/algorithm/for_each_n.hpp2
-rw-r--r--boost/compute/algorithm/gather.hpp2
-rw-r--r--boost/compute/algorithm/generate.hpp2
-rw-r--r--boost/compute/algorithm/generate_n.hpp2
-rw-r--r--boost/compute/algorithm/includes.hpp1
-rw-r--r--boost/compute/algorithm/inclusive_scan.hpp4
-rw-r--r--boost/compute/algorithm/inner_product.hpp3
-rw-r--r--boost/compute/algorithm/inplace_merge.hpp2
-rw-r--r--boost/compute/algorithm/iota.hpp2
-rw-r--r--boost/compute/algorithm/is_partitioned.hpp2
-rw-r--r--boost/compute/algorithm/is_permutation.hpp1
-rw-r--r--boost/compute/algorithm/is_sorted.hpp2
-rw-r--r--boost/compute/algorithm/lexicographical_compare.hpp11
-rw-r--r--boost/compute/algorithm/lower_bound.hpp2
-rw-r--r--boost/compute/algorithm/max_element.hpp3
-rw-r--r--boost/compute/algorithm/merge.hpp2
-rw-r--r--boost/compute/algorithm/min_element.hpp3
-rw-r--r--boost/compute/algorithm/minmax_element.hpp3
-rw-r--r--boost/compute/algorithm/mismatch.hpp2
-rw-r--r--boost/compute/algorithm/next_permutation.hpp1
-rw-r--r--boost/compute/algorithm/none_of.hpp2
-rw-r--r--boost/compute/algorithm/nth_element.hpp2
-rw-r--r--boost/compute/algorithm/partial_sum.hpp4
-rw-r--r--boost/compute/algorithm/partition.hpp2
-rw-r--r--boost/compute/algorithm/partition_copy.hpp2
-rw-r--r--boost/compute/algorithm/partition_point.hpp2
-rw-r--r--boost/compute/algorithm/prev_permutation.hpp1
-rw-r--r--boost/compute/algorithm/random_shuffle.hpp2
-rw-r--r--boost/compute/algorithm/reduce.hpp4
-rw-r--r--boost/compute/algorithm/reduce_by_key.hpp3
-rw-r--r--boost/compute/algorithm/remove.hpp2
-rw-r--r--boost/compute/algorithm/remove_if.hpp2
-rw-r--r--boost/compute/algorithm/replace.hpp2
-rw-r--r--boost/compute/algorithm/replace_copy.hpp2
-rw-r--r--boost/compute/algorithm/reverse.hpp2
-rw-r--r--boost/compute/algorithm/reverse_copy.hpp2
-rw-r--r--boost/compute/algorithm/rotate.hpp2
-rw-r--r--boost/compute/algorithm/rotate_copy.hpp2
-rw-r--r--boost/compute/algorithm/scatter.hpp2
-rw-r--r--boost/compute/algorithm/scatter_if.hpp2
-rw-r--r--boost/compute/algorithm/search.hpp1
-rw-r--r--boost/compute/algorithm/search_n.hpp1
-rw-r--r--boost/compute/algorithm/set_difference.hpp2
-rw-r--r--boost/compute/algorithm/set_intersection.hpp2
-rw-r--r--boost/compute/algorithm/set_symmetric_difference.hpp15
-rw-r--r--boost/compute/algorithm/set_union.hpp2
-rw-r--r--boost/compute/algorithm/sort.hpp2
-rw-r--r--boost/compute/algorithm/sort_by_key.hpp2
-rw-r--r--boost/compute/algorithm/stable_partition.hpp2
-rw-r--r--boost/compute/algorithm/stable_sort.hpp2
-rw-r--r--boost/compute/algorithm/stable_sort_by_key.hpp2
-rw-r--r--boost/compute/algorithm/swap_ranges.hpp2
-rw-r--r--boost/compute/algorithm/transform.hpp2
-rw-r--r--boost/compute/algorithm/transform_if.hpp9
-rw-r--r--boost/compute/algorithm/transform_reduce.hpp3
-rw-r--r--boost/compute/algorithm/unique.hpp2
-rw-r--r--boost/compute/algorithm/unique_copy.hpp2
-rw-r--r--boost/compute/algorithm/upper_bound.hpp2
-rw-r--r--boost/compute/buffer.hpp8
-rw-r--r--boost/compute/cl.hpp48
-rw-r--r--boost/compute/command_queue.hpp59
-rw-r--r--boost/compute/container/detail/scalar.hpp5
-rw-r--r--boost/compute/container/valarray.hpp1
-rw-r--r--boost/compute/context.hpp4
-rw-r--r--boost/compute/detail/buffer_value.hpp4
-rw-r--r--boost/compute/detail/duration.hpp4
-rw-r--r--boost/compute/detail/meta_kernel.hpp4
-rw-r--r--boost/compute/detail/parameter_cache.hpp14
-rw-r--r--boost/compute/detail/path.hpp2
-rw-r--r--boost/compute/detail/read_write_single_value.hpp17
-rw-r--r--boost/compute/device.hpp30
-rw-r--r--boost/compute/event.hpp12
-rw-r--r--boost/compute/exception/opencl_error.hpp6
-rw-r--r--boost/compute/function.hpp13
-rw-r--r--boost/compute/functional/atomic.hpp2
-rw-r--r--boost/compute/image/image1d.hpp8
-rw-r--r--boost/compute/image/image2d.hpp8
-rw-r--r--boost/compute/image/image3d.hpp8
-rw-r--r--boost/compute/image/image_sampler.hpp2
-rw-r--r--boost/compute/interop/opengl/context.hpp6
-rw-r--r--boost/compute/interop/opengl/opengl_texture.hpp2
-rw-r--r--boost/compute/iterator/buffer_iterator.hpp17
-rw-r--r--boost/compute/iterator/counting_iterator.hpp6
-rw-r--r--boost/compute/iterator/function_input_iterator.hpp2
-rw-r--r--boost/compute/iterator/permutation_iterator.hpp6
-rw-r--r--boost/compute/iterator/strided_iterator.hpp10
-rw-r--r--boost/compute/iterator/transform_iterator.hpp6
-rw-r--r--boost/compute/iterator/zip_iterator.hpp4
-rw-r--r--boost/compute/kernel.hpp18
-rw-r--r--boost/compute/lambda/context.hpp35
-rw-r--r--boost/compute/lambda/functional.hpp403
-rw-r--r--boost/compute/memory/svm_ptr.hpp14
-rw-r--r--boost/compute/memory_object.hpp10
-rw-r--r--boost/compute/pipe.hpp4
-rw-r--r--boost/compute/platform.hpp4
-rw-r--r--boost/compute/program.hpp81
-rw-r--r--boost/compute/svm.hpp4
-rw-r--r--boost/compute/system.hpp8
-rw-r--r--boost/compute/type_traits/type_definition.hpp5
-rw-r--r--boost/compute/types/tuple.hpp2
-rw-r--r--boost/compute/user_event.hpp4
-rw-r--r--boost/config.hpp8
-rw-r--r--boost/config/compiler/borland.hpp11
-rw-r--r--boost/config/compiler/clang.hpp19
-rw-r--r--boost/config/compiler/codegear.hpp13
-rw-r--r--boost/config/compiler/common_edg.hpp11
-rw-r--r--boost/config/compiler/diab.hpp19
-rw-r--r--boost/config/compiler/digitalmars.hpp11
-rw-r--r--boost/config/compiler/gcc.hpp22
-rw-r--r--boost/config/compiler/gcc_xml.hpp11
-rw-r--r--boost/config/compiler/metrowerks.hpp11
-rw-r--r--boost/config/compiler/mpw.hpp11
-rw-r--r--boost/config/compiler/nvcc.hpp19
-rw-r--r--boost/config/compiler/pathscale.hpp18
-rw-r--r--boost/config/compiler/pgi.hpp11
-rw-r--r--boost/config/compiler/sunpro_cc.hpp11
-rw-r--r--boost/config/compiler/vacpp.hpp11
-rw-r--r--boost/config/compiler/visualc.hpp9
-rw-r--r--boost/config/compiler/xlcpp.hpp14
-rw-r--r--boost/config/compiler/xlcpp_zos.hpp168
-rw-r--r--boost/config/detail/posix_features.hpp (renamed from boost/config/posix_features.hpp)0
-rw-r--r--boost/config/detail/select_compiler_config.hpp (renamed from boost/config/select_compiler_config.hpp)12
-rw-r--r--boost/config/detail/select_platform_config.hpp (renamed from boost/config/select_platform_config.hpp)11
-rw-r--r--boost/config/detail/select_stdlib_config.hpp (renamed from boost/config/select_stdlib_config.hpp)5
-rw-r--r--boost/config/detail/suffix.hpp (renamed from boost/config/suffix.hpp)22
-rw-r--r--boost/config/platform/aix.hpp2
-rw-r--r--boost/config/platform/beos.hpp2
-rw-r--r--boost/config/platform/bsd.hpp2
-rw-r--r--boost/config/platform/cray.hpp2
-rw-r--r--boost/config/platform/cygwin.hpp2
-rw-r--r--boost/config/platform/haiku.hpp2
-rw-r--r--boost/config/platform/hpux.hpp2
-rw-r--r--boost/config/platform/irix.hpp2
-rw-r--r--boost/config/platform/linux.hpp7
-rw-r--r--boost/config/platform/macos.hpp2
-rw-r--r--boost/config/platform/qnxnto.hpp2
-rw-r--r--boost/config/platform/solaris.hpp2
-rw-r--r--boost/config/platform/symbian.hpp2
-rw-r--r--boost/config/platform/vxworks.hpp41
-rw-r--r--boost/config/platform/zos.hpp32
-rw-r--r--boost/config/stdlib/dinkumware.hpp14
-rw-r--r--boost/config/stdlib/libcomo.hpp1
-rw-r--r--boost/config/stdlib/libcpp.hpp11
-rw-r--r--boost/config/stdlib/libstdcpp3.hpp32
-rw-r--r--boost/config/stdlib/modena.hpp1
-rw-r--r--boost/config/stdlib/msl.hpp3
-rw-r--r--boost/config/stdlib/roguewave.hpp1
-rw-r--r--boost/config/stdlib/sgi.hpp1
-rw-r--r--boost/config/stdlib/stlport.hpp1
-rw-r--r--boost/config/stdlib/vacpp.hpp1
-rw-r--r--boost/config/stdlib/xlcpp_zos.hpp59
-rw-r--r--boost/config/workaround.hpp277
-rw-r--r--boost/container/allocator_traits.hpp2
-rw-r--r--boost/container/deque.hpp20
-rw-r--r--boost/container/detail/adaptive_node_pool_impl.hpp16
-rw-r--r--boost/container/detail/advanced_insert_int.hpp10
-rw-r--r--boost/container/detail/algorithm.hpp122
-rw-r--r--boost/container/detail/copy_move_algo.hpp69
-rw-r--r--boost/container/detail/destroyers.hpp10
-rw-r--r--boost/container/detail/flat_tree.hpp332
-rw-r--r--boost/container/detail/iterator_to_raw_pointer.hpp29
-rw-r--r--boost/container/detail/multiallocation_chain.hpp6
-rw-r--r--boost/container/detail/node_alloc_holder.hpp34
-rw-r--r--boost/container/detail/node_pool_impl.hpp4
-rw-r--r--boost/container/detail/pair.hpp61
-rw-r--r--boost/container/detail/pair_key_mapped_of_value.hpp55
-rw-r--r--boost/container/detail/to_raw_pointer.hpp33
-rw-r--r--boost/container/detail/tree.hpp145
-rw-r--r--boost/container/flat_map.hpp830
-rw-r--r--boost/container/flat_set.hpp409
-rw-r--r--boost/container/map.hpp528
-rw-r--r--boost/container/node_handle.hpp188
-rw-r--r--boost/container/set.hpp349
-rw-r--r--boost/container/small_vector.hpp4
-rw-r--r--boost/container/stable_vector.hpp6
-rw-r--r--boost/container/string.hpp116
-rw-r--r--boost/container/vector.hpp149
-rw-r--r--boost/context/continuation.hpp551
-rw-r--r--boost/context/continuation_fcontext.hpp382
-rw-r--r--boost/context/continuation_ucontext.hpp525
-rw-r--r--boost/context/continuation_winfib.hpp453
-rw-r--r--boost/context/detail/config.hpp11
-rw-r--r--boost/context/detail/exception.hpp4
-rw-r--r--boost/context/detail/fcontext_arm.hpp68
-rw-r--r--boost/context/detail/fcontext_arm_mac.hpp70
-rw-r--r--boost/context/detail/fcontext_arm_win.hpp71
-rw-r--r--boost/context/detail/fcontext_i386.hpp59
-rw-r--r--boost/context/detail/fcontext_i386_win.hpp88
-rw-r--r--boost/context/detail/fcontext_mips.hpp70
-rw-r--r--boost/context/detail/fcontext_ppc.hpp72
-rw-r--r--boost/context/detail/fcontext_sparc.hpp90
-rw-r--r--boost/context/detail/fcontext_x86_64.hpp68
-rw-r--r--boost/context/detail/fcontext_x86_64_win.hpp77
-rw-r--r--boost/context/detail/prefetch.hpp78
-rw-r--r--boost/context/fixedsize_stack.hpp75
-rw-r--r--boost/context/pooled_fixedsize_stack.hpp1
-rw-r--r--boost/context/posix/fixedsize_stack.hpp80
-rw-r--r--boost/context/posix/protected_fixedsize_stack.hpp14
-rw-r--r--boost/context/windows/fixedsize_stack.hpp80
-rw-r--r--boost/context/windows/protected_fixedsize_stack.hpp14
-rw-r--r--boost/convert.hpp11
-rw-r--r--boost/convert/base.hpp56
-rw-r--r--boost/convert/detail/char.hpp28
-rw-r--r--boost/convert/detail/config.hpp (renamed from boost/convert/detail/forward.hpp)45
-rw-r--r--boost/convert/detail/has_member.hpp3
-rw-r--r--boost/convert/detail/is_converter.hpp2
-rw-r--r--boost/convert/detail/is_fun.hpp2
-rw-r--r--boost/convert/detail/is_string.hpp4
-rw-r--r--boost/convert/detail/range.hpp29
-rw-r--r--boost/convert/spirit.hpp2
-rw-r--r--boost/convert/strtol.hpp32
-rw-r--r--boost/core/addressof.hpp15
-rw-r--r--boost/core/lightweight_test.hpp82
-rw-r--r--boost/core/no_exceptions_support.hpp2
-rw-r--r--boost/core/pointer_traits.hpp258
-rw-r--r--boost/core/ref.hpp4
-rw-r--r--boost/coroutine2/detail/config.hpp8
-rw-r--r--boost/coroutine2/detail/coroutine.hpp28
-rw-r--r--boost/coroutine2/detail/pull_control_block_cc.hpp2
-rw-r--r--boost/coroutine2/detail/pull_control_block_cc.ipp38
-rw-r--r--boost/coroutine2/detail/pull_control_block_ecv1.hpp119
-rw-r--r--boost/coroutine2/detail/pull_control_block_ecv1.ipp431
-rw-r--r--boost/coroutine2/detail/push_control_block_cc.ipp47
-rw-r--r--boost/coroutine2/detail/push_control_block_ecv1.hpp111
-rw-r--r--boost/coroutine2/detail/push_control_block_ecv1.ipp428
-rw-r--r--boost/coroutine2/detail/wrap.hpp49
-rw-r--r--boost/cstdint.hpp16
-rw-r--r--boost/date_time/dst_rules.hpp12
-rw-r--r--boost/date_time/locale_config.hpp4
-rw-r--r--boost/date_time/posix_time/conversion.hpp20
-rw-r--r--boost/date_time/time_resolution_traits.hpp16
-rw-r--r--boost/detail/winapi/debugapi.hpp79
-rw-r--r--boost/detail/winapi/file_management.hpp18
-rw-r--r--boost/detail/winapi/jobs.hpp14
-rw-r--r--boost/detail/winapi/stack_backtrace.hpp55
-rw-r--r--boost/detail/workaround.hpp266
-rw-r--r--boost/dll/detail/pe_info.hpp7
-rw-r--r--boost/dynamic_bitset/dynamic_bitset.hpp104
-rw-r--r--boost/enable_shared_from_this.hpp2
-rw-r--r--boost/exception/N3757.hpp46
-rw-r--r--boost/exception/all.hpp11
-rw-r--r--boost/exception/detail/error_info_impl.hpp59
-rw-r--r--boost/exception/detail/exception_ptr.hpp19
-rw-r--r--boost/exception/detail/is_output_streamable.hpp5
-rw-r--r--boost/exception/detail/object_hex_dump.hpp13
-rw-r--r--boost/exception/detail/type_info.hpp13
-rw-r--r--boost/exception/diagnostic_information.hpp17
-rw-r--r--boost/exception/enable_current_exception.hpp5
-rw-r--r--boost/exception/enable_error_info.hpp5
-rw-r--r--boost/exception/errinfo_errno.hpp9
-rw-r--r--boost/exception/get_error_info.hpp14
-rw-r--r--boost/exception/info.hpp60
-rw-r--r--boost/exception/info_tuple.hpp7
-rw-r--r--boost/exception/to_string.hpp9
-rw-r--r--boost/exception/to_string_stub.hpp9
-rw-r--r--boost/fiber/algo/algorithm.hpp29
-rw-r--r--boost/fiber/algo/numa/work_stealing.hpp93
-rw-r--r--boost/fiber/algo/work_stealing.hpp34
-rw-r--r--boost/fiber/all.hpp3
-rw-r--r--boost/fiber/buffered_channel.hpp294
-rw-r--r--boost/fiber/condition_variable.hpp3
-rw-r--r--boost/fiber/context.hpp263
-rw-r--r--boost/fiber/detail/config.hpp21
-rw-r--r--boost/fiber/detail/context_spinlock_queue.hpp2
-rw-r--r--boost/fiber/detail/context_spmc_queue.hpp10
-rw-r--r--boost/fiber/detail/convert.hpp16
-rw-r--r--boost/fiber/detail/cpu_relax.hpp2
-rw-r--r--boost/fiber/detail/data.hpp17
-rw-r--r--boost/fiber/detail/futex.hpp12
-rw-r--r--boost/fiber/detail/rtm.hpp94
-rw-r--r--boost/fiber/detail/spinlock.hpp29
-rw-r--r--boost/fiber/detail/spinlock_rtm.hpp126
-rw-r--r--boost/fiber/detail/spinlock_status.hpp21
-rw-r--r--boost/fiber/detail/spinlock_ttas.hpp43
-rw-r--r--boost/fiber/detail/spinlock_ttas_adaptive.hpp46
-rw-r--r--boost/fiber/detail/spinlock_ttas_adaptive_futex.hpp63
-rw-r--r--boost/fiber/detail/spinlock_ttas_futex.hpp51
-rw-r--r--boost/fiber/detail/wrap.hpp131
-rw-r--r--boost/fiber/fiber.hpp47
-rw-r--r--boost/fiber/fss.hpp6
-rw-r--r--boost/fiber/future/async.hpp8
-rw-r--r--boost/fiber/future/detail/shared_state.hpp14
-rw-r--r--boost/fiber/future/detail/task_object.hpp13
-rw-r--r--boost/fiber/future/future.hpp48
-rw-r--r--boost/fiber/future/packaged_task.hpp15
-rw-r--r--boost/fiber/future/promise.hpp24
-rw-r--r--boost/fiber/numa/pin_thread.hpp33
-rw-r--r--boost/fiber/numa/topology.hpp46
-rw-r--r--boost/fiber/operations.hpp16
-rw-r--r--boost/fiber/properties.hpp2
-rw-r--r--boost/fiber/scheduler.hpp16
-rw-r--r--boost/fiber/type.hpp1
-rw-r--r--boost/fiber/unbuffered_channel.hpp252
-rw-r--r--boost/functional/hash/hash.hpp22
-rw-r--r--boost/fusion/container/deque/deque_fwd.hpp3
-rw-r--r--boost/fusion/container/map/map_fwd.hpp3
-rw-r--r--boost/fusion/container/vector/detail/config.hpp3
-rw-r--r--boost/fusion/include/std_array.hpp (renamed from boost/fusion/include/adapt_adt_named.cpp)8
-rw-r--r--boost/geometry/algorithms/correct.hpp95
-rw-r--r--boost/geometry/algorithms/covered_by.hpp439
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp221
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp45
-rw-r--r--boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp38
-rw-r--r--boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp10
-rw-r--r--boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp27
-rw-r--r--boost/geometry/algorithms/detail/covered_by/implementation.hpp280
-rw-r--r--boost/geometry/algorithms/detail/covered_by/interface.hpp261
-rw-r--r--boost/geometry/algorithms/detail/direction_code.hpp221
-rw-r--r--boost/geometry/algorithms/detail/disjoint/box_box.hpp13
-rw-r--r--boost/geometry/algorithms/detail/disjoint/implementation.hpp4
-rw-r--r--boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp249
-rw-r--r--boost/geometry/algorithms/detail/disjoint/segment_box.hpp167
-rw-r--r--boost/geometry/algorithms/detail/envelope/segment.hpp125
-rw-r--r--boost/geometry/algorithms/detail/equals/implementation.hpp397
-rw-r--r--boost/geometry/algorithms/detail/equals/interface.hpp317
-rw-r--r--boost/geometry/algorithms/detail/extreme_points.hpp93
-rw-r--r--boost/geometry/algorithms/detail/get_left_turns.hpp40
-rw-r--r--boost/geometry/algorithms/detail/has_self_intersections.hpp2
-rw-r--r--boost/geometry/algorithms/detail/intersects/implementation.hpp88
-rw-r--r--boost/geometry/algorithms/detail/intersects/interface.hpp115
-rw-r--r--boost/geometry/algorithms/detail/is_simple/linear.hpp48
-rw-r--r--boost/geometry/algorithms/detail/is_valid/has_spikes.hpp15
-rw-r--r--boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp2
-rw-r--r--boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp13
-rw-r--r--boost/geometry/algorithms/detail/is_valid/linear.hpp36
-rw-r--r--boost/geometry/algorithms/detail/is_valid/multipolygon.hpp75
-rw-r--r--boost/geometry/algorithms/detail/is_valid/polygon.hpp155
-rw-r--r--boost/geometry/algorithms/detail/is_valid/ring.hpp7
-rw-r--r--boost/geometry/algorithms/detail/multi_modify.hpp16
-rw-r--r--boost/geometry/algorithms/detail/occupation_info.hpp19
-rw-r--r--boost/geometry/algorithms/detail/overlaps/implementation.hpp156
-rw-r--r--boost/geometry/algorithms/detail/overlaps/interface.hpp124
-rw-r--r--boost/geometry/algorithms/detail/overlay/aggregate_operations.hpp166
-rw-r--r--boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp13
-rw-r--r--boost/geometry/algorithms/detail/overlay/assign_parents.hpp136
-rw-r--r--boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp1
-rw-r--r--boost/geometry/algorithms/detail/overlay/copy_segments.hpp34
-rw-r--r--boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp172
-rw-r--r--boost/geometry/algorithms/detail/overlay/enrichment_info.hpp13
-rw-r--r--boost/geometry/algorithms/detail/overlay/follow.hpp121
-rw-r--r--boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp41
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_relative_order.hpp32
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info.hpp14
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp2
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turns.hpp34
-rw-r--r--boost/geometry/algorithms/detail/overlay/handle_colocations.hpp148
-rw-r--r--boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp143
-rw-r--r--boost/geometry/algorithms/detail/overlay/intersection_insert.hpp46
-rw-r--r--boost/geometry/algorithms/detail/overlay/is_self_turn.hpp68
-rw-r--r--boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp24
-rw-r--r--boost/geometry/algorithms/detail/overlay/linear_linear.hpp10
-rw-r--r--boost/geometry/algorithms/detail/overlay/overlay.hpp134
-rw-r--r--boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp69
-rw-r--r--boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp178
-rw-r--r--boost/geometry/algorithms/detail/overlay/ring_properties.hpp19
-rw-r--r--boost/geometry/algorithms/detail/overlay/select_rings.hpp114
-rw-r--r--boost/geometry/algorithms/detail/overlay/self_turn_points.hpp151
-rw-r--r--boost/geometry/algorithms/detail/overlay/sort_by_side.hpp160
-rw-r--r--boost/geometry/algorithms/detail/overlay/traversal.hpp434
-rw-r--r--boost/geometry/algorithms/detail/overlay/traversal_intersection_patterns.hpp306
-rw-r--r--boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp42
-rw-r--r--boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp408
-rw-r--r--boost/geometry/algorithms/detail/overlay/turn_info.hpp11
-rw-r--r--boost/geometry/algorithms/detail/partition.hpp294
-rw-r--r--boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp76
-rw-r--r--boost/geometry/algorithms/detail/point_on_border.hpp193
-rw-r--r--boost/geometry/algorithms/detail/relate/implementation.hpp11
-rw-r--r--boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp568
-rw-r--r--boost/geometry/algorithms/detail/relate/point_geometry.hpp38
-rw-r--r--boost/geometry/algorithms/detail/relate/point_point.hpp54
-rw-r--r--boost/geometry/algorithms/detail/relate/topology_check.hpp244
-rw-r--r--boost/geometry/algorithms/detail/sections/section_functions.hpp96
-rw-r--r--boost/geometry/algorithms/detail/sections/sectionalize.hpp194
-rw-r--r--boost/geometry/algorithms/detail/touches/implementation.hpp459
-rw-r--r--boost/geometry/algorithms/detail/touches/interface.hpp321
-rw-r--r--boost/geometry/algorithms/detail/within/implementation.hpp306
-rw-r--r--boost/geometry/algorithms/detail/within/interface.hpp304
-rw-r--r--boost/geometry/algorithms/detail/within/multi_point.hpp268
-rw-r--r--boost/geometry/algorithms/equals.hpp645
-rw-r--r--boost/geometry/algorithms/intersects.hpp116
-rw-r--r--boost/geometry/algorithms/is_convex.hpp92
-rw-r--r--boost/geometry/algorithms/overlaps.hpp210
-rw-r--r--boost/geometry/algorithms/point_on_surface.hpp56
-rw-r--r--boost/geometry/algorithms/remove_spikes.hpp112
-rw-r--r--boost/geometry/algorithms/touches.hpp683
-rw-r--r--boost/geometry/algorithms/within.hpp500
-rw-r--r--boost/geometry/core/radian_access.hpp107
-rw-r--r--boost/geometry/formulas/vertex_longitude.hpp339
-rw-r--r--boost/geometry/index/detail/algorithms/intersection_content.hpp21
-rw-r--r--boost/geometry/index/detail/algorithms/path_intersection.hpp6
-rw-r--r--boost/geometry/index/detail/rtree/node/variant_dynamic.hpp4
-rw-r--r--boost/geometry/index/detail/rtree/node/weak_dynamic.hpp2
-rw-r--r--boost/geometry/index/detail/rtree/visitors/remove.hpp4
-rw-r--r--boost/geometry/index/equal_to.hpp2
-rw-r--r--boost/geometry/index/indexable.hpp3
-rw-r--r--boost/geometry/index/rtree.hpp24
-rw-r--r--boost/geometry/strategies/agnostic/point_in_point.hpp20
-rw-r--r--boost/geometry/strategies/agnostic/point_in_poly_winding.hpp94
-rw-r--r--boost/geometry/strategies/cartesian/disjoint_segment_box.hpp9
-rw-r--r--boost/geometry/strategies/cartesian/envelope_segment.hpp1
-rw-r--r--boost/geometry/strategies/cartesian/intersection.hpp9
-rw-r--r--boost/geometry/strategies/cartesian/side_by_triangle.hpp16
-rw-r--r--boost/geometry/strategies/disjoint.hpp5
-rw-r--r--boost/geometry/strategies/geographic/area.hpp23
-rw-r--r--boost/geometry/strategies/geographic/azimuth.hpp18
-rw-r--r--boost/geometry/strategies/geographic/disjoint_segment_box.hpp130
-rw-r--r--boost/geometry/strategies/geographic/intersection.hpp148
-rw-r--r--boost/geometry/strategies/geographic/side.hpp26
-rw-r--r--boost/geometry/strategies/spherical/azimuth.hpp18
-rw-r--r--boost/geometry/strategies/spherical/disjoint_segment_box.hpp105
-rw-r--r--boost/geometry/strategies/spherical/intersection.hpp191
-rw-r--r--boost/geometry/strategies/spherical/ssf.hpp16
-rw-r--r--boost/geometry/strategies/strategies.hpp2
-rw-r--r--boost/hana.hpp1
-rw-r--r--boost/hana/at_key.hpp38
-rw-r--r--boost/hana/basic_tuple.hpp11
-rw-r--r--boost/hana/detail/index_if.hpp68
-rw-r--r--boost/hana/detail/struct_macros.hpp.erb (renamed from boost/hana/detail/struct_macros.erb.hpp)2
-rw-r--r--boost/hana/detail/variadic/foldl1.hpp2
-rw-r--r--boost/hana/detail/variadic/foldr1.hpp2
-rw-r--r--boost/hana/difference.hpp1
-rw-r--r--boost/hana/experimental/view.hpp1
-rw-r--r--boost/hana/ext/std/array.hpp18
-rw-r--r--boost/hana/find_if.hpp78
-rw-r--r--boost/hana/fwd/adjust_if.hpp2
-rw-r--r--boost/hana/fwd/core/tag_of.hpp2
-rw-r--r--boost/hana/fwd/difference.hpp40
-rw-r--r--boost/hana/fwd/index_if.hpp60
-rw-r--r--boost/hana/fwd/intersection.hpp29
-rw-r--r--boost/hana/fwd/map.hpp120
-rw-r--r--boost/hana/fwd/replace_if.hpp2
-rw-r--r--boost/hana/fwd/set.hpp107
-rw-r--r--boost/hana/fwd/symmetric_difference.hpp30
-rw-r--r--boost/hana/fwd/union.hpp33
-rw-r--r--boost/hana/index_if.hpp105
-rw-r--r--boost/hana/map.hpp69
-rw-r--r--boost/hana/pair.hpp16
-rw-r--r--boost/hana/tuple.hpp34
-rw-r--r--boost/hana/version.hpp2
-rw-r--r--boost/integer/common_factor_rt.hpp898
-rw-r--r--boost/integer/integer_mask.hpp10
-rw-r--r--boost/integer_fwd.hpp3
-rw-r--r--boost/interprocess/indexes/iunordered_set_index.hpp4
-rw-r--r--boost/interprocess/indexes/unordered_map_index.hpp5
-rw-r--r--boost/intrusive/bstree.hpp3
-rw-r--r--boost/intrusive/detail/default_header_holder.hpp4
-rw-r--r--boost/intrusive/detail/ebo_functor_holder.hpp2
-rw-r--r--boost/intrusive/detail/hashtable_node.hpp2
-rw-r--r--boost/intrusive/detail/hook_traits.hpp10
-rw-r--r--boost/intrusive/detail/iterator.hpp110
-rw-r--r--boost/intrusive/detail/node_to_value.hpp2
-rw-r--r--boost/intrusive/detail/to_raw_pointer.hpp47
-rw-r--r--boost/intrusive/detail/tree_value_compare.hpp12
-rw-r--r--boost/intrusive/hashtable.hpp127
-rw-r--r--boost/intrusive/member_value_traits.hpp6
-rw-r--r--boost/intrusive/pointer_traits.hpp4
-rw-r--r--boost/intrusive_ptr.hpp2
-rwxr-xr-xboost/iostreams/detail/adapter/non_blocking_adapter.hpp3
-rw-r--r--boost/iostreams/detail/config/dyn_link.hpp11
-rw-r--r--boost/iostreams/filter/gzip.hpp2
-rw-r--r--boost/iostreams/filter/lzma.hpp364
-rw-r--r--boost/iterator/advance.hpp84
-rw-r--r--boost/iterator/distance.hpp65
-rw-r--r--boost/iterator/reverse_iterator.hpp10
-rw-r--r--boost/iterator/zip_iterator.hpp2
-rw-r--r--boost/locale/message.hpp7
-rw-r--r--boost/log/core/record_view.hpp2
-rw-r--r--boost/log/detail/config.hpp5
-rw-r--r--boost/make_shared.hpp3
-rw-r--r--boost/math/common_factor_ct.hpp79
-rw-r--r--boost/math/common_factor_rt.hpp419
-rw-r--r--boost/math/concepts/std_real_concept.hpp4
-rw-r--r--boost/math/constants/constants.hpp3
-rw-r--r--boost/math/interpolators/barycentric_rational.hpp70
-rw-r--r--boost/math/interpolators/cubic_b_spline.hpp78
-rw-r--r--boost/math/interpolators/detail/barycentric_rational_detail.hpp151
-rw-r--r--boost/math/interpolators/detail/cubic_b_spline_detail.hpp287
-rw-r--r--boost/math/quadrature/trapezoidal.hpp120
-rw-r--r--boost/math/special_functions/detail/airy_ai_bi_zero.hpp4
-rw-r--r--boost/math/special_functions/detail/bessel_i0.hpp2
-rw-r--r--boost/math/special_functions/detail/bessel_i1.hpp2
-rw-r--r--boost/math/special_functions/detail/bessel_k0.hpp2
-rw-r--r--boost/math/special_functions/detail/bessel_k1.hpp2
-rw-r--r--boost/math/special_functions/legendre.hpp191
-rw-r--r--boost/math/special_functions/legendre_stieltjes.hpp235
-rw-r--r--boost/math/special_functions/math_fwd.hpp21
-rw-r--r--boost/math/special_functions/next.hpp384
-rw-r--r--boost/math/special_functions/sign.hpp2
-rw-r--r--boost/math/special_functions/ulp.hpp38
-rw-r--r--boost/math/tools/polynomial.hpp6
-rw-r--r--boost/math/tools/polynomial_gcd.hpp209
-rw-r--r--boost/math_fwd.hpp46
-rw-r--r--boost/metaparse/config.hpp35
-rw-r--r--boost/metaparse/v1/cpp11/fwd/string.hpp22
-rw-r--r--boost/metaparse/v1/cpp11/impl/at_c.hpp35
-rw-r--r--boost/metaparse/v1/cpp11/impl/concat.hpp30
-rw-r--r--boost/metaparse/v1/cpp11/impl/empty_string.hpp33
-rw-r--r--boost/metaparse/v1/cpp11/impl/pop_back.hpp (renamed from boost/metaparse/v1/impl/pop_back.hpp)23
-rw-r--r--boost/metaparse/v1/cpp11/impl/pop_front.hpp30
-rw-r--r--boost/metaparse/v1/cpp11/impl/push_back_c.hpp30
-rw-r--r--boost/metaparse/v1/cpp11/impl/push_front_c.hpp30
-rw-r--r--boost/metaparse/v1/cpp11/impl/remove_trailing_no_chars.hpp (renamed from boost/metaparse/v1/impl/remove_trailing_no_chars.hpp)12
-rw-r--r--boost/metaparse/v1/cpp11/impl/size.hpp34
-rw-r--r--boost/metaparse/v1/cpp11/impl/string.hpp (renamed from boost/metaparse/v1/impl/string.hpp)6
-rw-r--r--boost/metaparse/v1/cpp11/impl/string_at.hpp (renamed from boost/metaparse/v1/impl/string_at.hpp)12
-rw-r--r--boost/metaparse/v1/cpp11/string.hpp213
-rw-r--r--boost/metaparse/v1/cpp98/fwd/string.hpp33
-rw-r--r--boost/metaparse/v1/cpp98/impl/at_c.hpp58
-rw-r--r--boost/metaparse/v1/cpp98/impl/empty_string.hpp33
-rw-r--r--boost/metaparse/v1/cpp98/impl/pop_back.hpp39
-rw-r--r--boost/metaparse/v1/cpp98/impl/pop_front.hpp (renamed from boost/metaparse/v1/impl/pop_front.hpp)12
-rw-r--r--boost/metaparse/v1/cpp98/impl/push_back_c.hpp (renamed from boost/metaparse/v1/impl/push_back_c.hpp)16
-rw-r--r--boost/metaparse/v1/cpp98/impl/push_front_c.hpp (renamed from boost/metaparse/v1/impl/push_front_c.hpp)12
-rw-r--r--boost/metaparse/v1/cpp98/impl/size.hpp (renamed from boost/metaparse/v1/impl/size.hpp)12
-rw-r--r--boost/metaparse/v1/cpp98/impl/update_c.hpp (renamed from boost/metaparse/v1/impl/update_c.hpp)25
-rw-r--r--boost/metaparse/v1/cpp98/string.hpp272
-rw-r--r--boost/metaparse/v1/fwd/string.hpp28
-rw-r--r--boost/metaparse/v1/impl/at_c.hpp54
-rw-r--r--boost/metaparse/v1/impl/concat.hpp106
-rw-r--r--boost/metaparse/v1/impl/empty_string.hpp44
-rw-r--r--boost/metaparse/v1/impl/split_at_c.hpp99
-rw-r--r--boost/metaparse/v1/string.hpp346
-rw-r--r--boost/move/algo/adaptive_sort.hpp15
-rw-r--r--boost/move/algo/detail/adaptive_sort_merge.hpp95
-rw-r--r--boost/move/algo/detail/basic_op.hpp20
-rw-r--r--boost/move/algo/detail/insertion_sort.hpp19
-rw-r--r--boost/move/algo/detail/merge.hpp80
-rw-r--r--boost/move/algo/detail/merge_sort.hpp12
-rw-r--r--boost/move/algo/move.hpp3
-rw-r--r--boost/move/algo/predicate.hpp86
-rw-r--r--boost/move/algo/unique.hpp55
-rw-r--r--boost/move/detail/destruct_n.hpp7
-rw-r--r--boost/move/detail/fwd_macros.hpp25
-rw-r--r--boost/move/detail/iterator_to_raw_pointer.hpp59
-rw-r--r--boost/move/detail/pointer_element.hpp (renamed from boost/intrusive/detail/pointer_element.hpp)24
-rw-r--r--boost/move/detail/to_raw_pointer.hpp45
-rw-r--r--boost/move/detail/unique_ptr_meta_utils.hpp2
-rw-r--r--boost/mpi/detail/antiques.hpp29
-rw-r--r--boost/mpi/detail/mpi_datatype_primitive.hpp14
-rw-r--r--boost/mpi/detail/packed_iprimitive.hpp4
-rw-r--r--boost/mpi/detail/packed_oprimitive.hpp7
-rw-r--r--boost/mpi/python/serialize.hpp1
-rw-r--r--boost/multiprecision/cpp_bin_float.hpp58
-rw-r--r--boost/multiprecision/cpp_bin_float/transcendental.hpp11
-rw-r--r--boost/multiprecision/cpp_dec_float.hpp8
-rw-r--r--boost/multiprecision/cpp_int/multiply.hpp22
-rw-r--r--boost/multiprecision/detail/bitscan.hpp11
-rw-r--r--boost/multiprecision/detail/default_ops.hpp13
-rw-r--r--boost/multiprecision/detail/functions/constants.hpp17
-rw-r--r--boost/multiprecision/detail/functions/pow.hpp10
-rw-r--r--boost/multiprecision/detail/functions/trig.hpp23
-rw-r--r--boost/multiprecision/detail/number_base.hpp29
-rw-r--r--boost/multiprecision/float128.hpp2
-rw-r--r--boost/multiprecision/gmp.hpp2
-rw-r--r--boost/multiprecision/number.hpp3
-rw-r--r--boost/multiprecision/traits/is_backend.hpp6
-rw-r--r--boost/multiprecision/traits/is_byte_container.hpp4
-rw-r--r--boost/next_prior.hpp125
-rw-r--r--boost/numeric/interval.hpp2
-rw-r--r--boost/numeric/interval/arith.hpp2
-rw-r--r--boost/numeric/interval/arith2.hpp2
-rw-r--r--boost/numeric/interval/checking.hpp2
-rw-r--r--boost/numeric/interval/compare.hpp2
-rw-r--r--boost/numeric/interval/compare/explicit.hpp2
-rw-r--r--boost/numeric/interval/constants.hpp2
-rw-r--r--boost/numeric/interval/detail/alpha_rounding_control.hpp2
-rw-r--r--boost/numeric/interval/detail/bcc_rounding_control.hpp2
-rw-r--r--boost/numeric/interval/detail/bugs.hpp2
-rw-r--r--boost/numeric/interval/detail/c99_rounding_control.hpp2
-rw-r--r--boost/numeric/interval/detail/c99sub_rounding_control.hpp2
-rw-r--r--boost/numeric/interval/detail/interval_prototype.hpp2
-rw-r--r--boost/numeric/interval/detail/msvc_rounding_control.hpp4
-rw-r--r--boost/numeric/interval/detail/ppc_rounding_control.hpp2
-rw-r--r--boost/numeric/interval/detail/sparc_rounding_control.hpp2
-rw-r--r--boost/numeric/interval/detail/test_input.hpp2
-rw-r--r--boost/numeric/interval/detail/x86_rounding_control.hpp2
-rw-r--r--boost/numeric/interval/detail/x86gcc_rounding_control.hpp2
-rw-r--r--boost/numeric/interval/ext/x86_fast_rounding_control.hpp2
-rw-r--r--boost/numeric/interval/interval.hpp2
-rw-r--r--boost/numeric/interval/limits.hpp2
-rw-r--r--boost/numeric/interval/rounded_arith.hpp2
-rw-r--r--boost/numeric/interval/rounded_transc.hpp2
-rw-r--r--boost/numeric/interval/rounding.hpp2
-rw-r--r--boost/numeric/interval/transc.hpp2
-rw-r--r--boost/numeric/interval/utility.hpp3
-rw-r--r--boost/numeric/odeint/integrate/integrate_n_steps.hpp1
-rw-r--r--boost/numeric/odeint/integrate/max_step_checker.hpp6
-rw-r--r--boost/numeric/odeint/stepper/adams_bashforth_moulton.hpp13
-rw-r--r--boost/numeric/odeint/stepper/bulirsch_stoer.hpp23
-rw-r--r--boost/numeric/odeint/stepper/bulirsch_stoer_dense_out.hpp10
-rw-r--r--boost/numeric/odeint/stepper/controlled_runge_kutta.hpp2
-rw-r--r--boost/numeric/odeint/stepper/rosenbrock4_controller.hpp2
-rw-r--r--boost/parameter/aux_/arg_list.hpp1
-rw-r--r--boost/phoenix/config.hpp4
-rw-r--r--boost/phoenix/stl/algorithm/detail/is_std_hash_map.hpp50
-rw-r--r--boost/phoenix/stl/algorithm/detail/is_std_hash_set.hpp46
-rw-r--r--boost/phoenix/stl/algorithm/detail/is_std_list.hpp2
-rw-r--r--boost/phoenix/stl/algorithm/detail/is_std_map.hpp2
-rw-r--r--boost/phoenix/stl/algorithm/detail/is_std_set.hpp2
-rw-r--r--boost/phoenix/stl/algorithm/detail/is_unordered_set_or_map.hpp7
-rw-r--r--boost/phoenix/stl/algorithm/detail/std_hash_map_fwd.hpp70
-rw-r--r--boost/phoenix/stl/algorithm/detail/std_hash_set_fwd.hpp62
-rw-r--r--boost/phoenix/stl/algorithm/detail/std_unordered_set_or_map_fwd.hpp74
-rw-r--r--boost/phoenix/stl/algorithm/transformation.hpp4
-rw-r--r--boost/phoenix/stl/container/container.hpp39
-rw-r--r--boost/phoenix/stl/container/detail/container.hpp42
-rw-r--r--boost/pointer_cast.hpp19
-rw-r--r--boost/pointer_to_other.hpp2
-rw-r--r--boost/poly_collection/algorithm.hpp1065
-rw-r--r--boost/poly_collection/any_collection.hpp80
-rw-r--r--boost/poly_collection/any_collection_fwd.hpp56
-rw-r--r--boost/poly_collection/base_collection.hpp79
-rw-r--r--boost/poly_collection/base_collection_fwd.hpp45
-rw-r--r--boost/poly_collection/detail/any_iterator.hpp92
-rw-r--r--boost/poly_collection/detail/any_model.hpp214
-rw-r--r--boost/poly_collection/detail/auto_iterator.hpp56
-rw-r--r--boost/poly_collection/detail/base_model.hpp130
-rw-r--r--boost/poly_collection/detail/callable_wrapper.hpp104
-rw-r--r--boost/poly_collection/detail/callable_wrapper_iterator.hpp95
-rw-r--r--boost/poly_collection/detail/function_model.hpp137
-rw-r--r--boost/poly_collection/detail/functional.hpp196
-rw-r--r--boost/poly_collection/detail/integer_sequence.hpp64
-rw-r--r--boost/poly_collection/detail/is_acceptable.hpp44
-rw-r--r--boost/poly_collection/detail/is_constructible.hpp61
-rw-r--r--boost/poly_collection/detail/is_equality_comparable.hpp89
-rw-r--r--boost/poly_collection/detail/is_final.hpp68
-rw-r--r--boost/poly_collection/detail/is_invocable.hpp97
-rw-r--r--boost/poly_collection/detail/is_likely_stateless_lambda.hpp70
-rw-r--r--boost/poly_collection/detail/is_nothrow_eq_comparable.hpp46
-rw-r--r--boost/poly_collection/detail/iterator_impl.hpp242
-rw-r--r--boost/poly_collection/detail/iterator_traits.hpp116
-rw-r--r--boost/poly_collection/detail/newdelete_allocator.hpp102
-rw-r--r--boost/poly_collection/detail/packed_segment.hpp318
-rw-r--r--boost/poly_collection/detail/poly_collection.hpp1176
-rw-r--r--boost/poly_collection/detail/segment.hpp296
-rw-r--r--boost/poly_collection/detail/segment_backend.hpp82
-rw-r--r--boost/poly_collection/detail/segment_split.hpp154
-rw-r--r--boost/poly_collection/detail/split_segment.hpp487
-rw-r--r--boost/poly_collection/detail/stride_iterator.hpp123
-rw-r--r--boost/poly_collection/detail/type_info_map.hpp169
-rw-r--r--boost/poly_collection/detail/type_restitution.hpp199
-rw-r--r--boost/poly_collection/detail/value_holder.hpp313
-rw-r--r--boost/poly_collection/exception.hpp57
-rw-r--r--boost/poly_collection/function_collection.hpp80
-rw-r--r--boost/poly_collection/function_collection_fwd.hpp57
-rw-r--r--boost/predef/architecture/arm.h7
-rw-r--r--boost/predef/compiler/intel.h9
-rw-r--r--boost/predef/hardware/simd/arm.h4
-rw-r--r--boost/predef/other/workaround.h87
-rw-r--r--boost/predef/platform.h1
-rw-r--r--boost/predef/platform/ios.h58
-rw-r--r--boost/predef/platform/mingw.h4
-rw-r--r--boost/predef/version.h2
-rw-r--r--boost/preprocessor/config/config.hpp16
-rw-r--r--boost/program_options/detail/value_semantic.hpp17
-rw-r--r--boost/program_options/eof_iterator.hpp6
-rw-r--r--boost/program_options/errors.hpp9
-rw-r--r--boost/program_options/option.hpp1
-rw-r--r--boost/program_options/value_semantic.hpp15
-rw-r--r--boost/program_options/version.hpp3
-rw-r--r--boost/python.hpp1
-rwxr-xr-xboost/python/arg_from_python.hpp6
-rw-r--r--boost/python/args.hpp11
-rw-r--r--boost/python/bases.hpp2
-rwxr-xr-xboost/python/cast.hpp9
-rw-r--r--boost/python/class.hpp16
-rw-r--r--boost/python/converter/arg_from_python.hpp5
-rwxr-xr-xboost/python/converter/arg_to_python.hpp12
-rw-r--r--boost/python/converter/object_manager.hpp2
-rw-r--r--boost/python/converter/pointer_type_id.hpp4
-rwxr-xr-xboost/python/converter/pytype_function.hpp9
-rw-r--r--boost/python/converter/registered.hpp8
-rw-r--r--boost/python/converter/registered_pointee.hpp9
-rwxr-xr-xboost/python/converter/return_from_python.hpp2
-rw-r--r--boost/python/converter/rvalue_from_python_data.hpp8
-rw-r--r--boost/python/data_members.hpp59
-rw-r--r--boost/python/default_call_policies.hpp6
-rw-r--r--boost/python/detail/borrowed_ptr.hpp3
-rw-r--r--boost/python/detail/caller.hpp6
-rw-r--r--boost/python/detail/config.hpp6
-rwxr-xr-xboost/python/detail/convertible.hpp4
-rw-r--r--boost/python/detail/cv_category.hpp6
-rw-r--r--boost/python/detail/dealloc.hpp2
-rw-r--r--boost/python/detail/decorated_type_id.hpp2
-rw-r--r--boost/python/detail/def_helper.hpp6
-rw-r--r--boost/python/detail/defaults_def.hpp4
-rw-r--r--boost/python/detail/destroy.hpp6
-rw-r--r--boost/python/detail/invoke.hpp2
-rw-r--r--boost/python/detail/pointee.hpp2
-rw-r--r--boost/python/detail/result.hpp2
-rw-r--r--boost/python/detail/string_literal.hpp3
-rw-r--r--boost/python/detail/translate_exception.hpp6
-rw-r--r--boost/python/detail/type_traits.hpp110
-rwxr-xr-xboost/python/detail/unwind_type.hpp6
-rwxr-xr-xboost/python/detail/value_arg.hpp5
-rw-r--r--boost/python/detail/value_is_xxx.hpp9
-rw-r--r--boost/python/detail/void_ptr.hpp2
-rw-r--r--boost/python/detail/wrapper_base.hpp9
-rw-r--r--boost/python/exec.hpp16
-rw-r--r--boost/python/init.hpp2
-rw-r--r--boost/python/iterator.hpp6
-rw-r--r--boost/python/lvalue_from_pytype.hpp3
-rw-r--r--boost/python/make_constructor.hpp8
-rw-r--r--boost/python/manage_new_object.hpp4
-rw-r--r--boost/python/numeric.hpp242
-rw-r--r--boost/python/numpy/config.hpp8
-rw-r--r--boost/python/numpy/dtype.hpp7
-rw-r--r--boost/python/numpy/internal.hpp1
-rw-r--r--boost/python/numpy/ndarray.hpp4
-rw-r--r--boost/python/object/class_metadata.hpp36
-rw-r--r--boost/python/object/forward.hpp11
-rw-r--r--boost/python/object/inheritance.hpp7
-rw-r--r--boost/python/object/instance.hpp6
-rw-r--r--boost/python/object/iterator.hpp9
-rw-r--r--boost/python/object/make_instance.hpp5
-rw-r--r--boost/python/object/make_ptr_instance.hpp8
-rw-r--r--boost/python/object/pointer_holder.hpp5
-rw-r--r--boost/python/object_core.hpp17
-rw-r--r--boost/python/opaque_pointer_converter.hpp7
-rw-r--r--boost/python/pointee.hpp10
-rw-r--r--boost/python/reference_existing_object.hpp4
-rw-r--r--boost/python/return_arg.hpp3
-rw-r--r--boost/python/return_by_value.hpp3
-rw-r--r--boost/python/return_opaque_pointer.hpp2
-rw-r--r--boost/python/signature.hpp4
-rw-r--r--boost/python/suite/indexing/detail/indexing_suite_detail.hpp6
-rw-r--r--boost/python/suite/indexing/indexing_suite.hpp10
-rw-r--r--boost/python/to_python_indirect.hpp15
-rw-r--r--boost/python/to_python_value.hpp4
-rw-r--r--boost/python/type_id.hpp2
-rw-r--r--boost/qvm/detail/mat_assign.hpp75
-rw-r--r--boost/qvm/detail/quat_assign.hpp35
-rw-r--r--boost/qvm/detail/vec_assign.hpp71
-rw-r--r--boost/qvm/gen/mat_assign2.hpp125
-rw-r--r--boost/qvm/gen/mat_assign3.hpp132
-rw-r--r--boost/qvm/gen/mat_assign4.hpp141
-rw-r--r--boost/qvm/gen/mat_operations2.hpp107
-rw-r--r--boost/qvm/gen/mat_operations3.hpp114
-rw-r--r--boost/qvm/gen/mat_operations4.hpp123
-rw-r--r--boost/qvm/gen/swizzle2.hpp6
-rw-r--r--boost/qvm/gen/swizzle3.hpp6
-rw-r--r--boost/qvm/gen/swizzle4.hpp6
-rw-r--r--boost/qvm/gen/vec_assign2.hpp56
-rw-r--r--boost/qvm/gen/vec_assign3.hpp57
-rw-r--r--boost/qvm/gen/vec_assign4.hpp58
-rw-r--r--boost/qvm/gen/vec_mat_operations2.hpp7
-rw-r--r--boost/qvm/gen/vec_mat_operations3.hpp7
-rw-r--r--boost/qvm/gen/vec_mat_operations4.hpp7
-rw-r--r--boost/qvm/gen/vec_operations2.hpp42
-rw-r--r--boost/qvm/gen/vec_operations3.hpp43
-rw-r--r--boost/qvm/gen/vec_operations4.hpp44
-rw-r--r--boost/qvm/mat.hpp2
-rw-r--r--boost/qvm/mat_operations.hpp57
-rw-r--r--boost/qvm/quat.hpp2
-rw-r--r--boost/qvm/quat_operations.hpp17
-rw-r--r--boost/qvm/vec.hpp2
-rw-r--r--boost/qvm/vec_operations.hpp53
-rw-r--r--boost/scoped_array.hpp3
-rw-r--r--boost/scoped_ptr.hpp3
-rw-r--r--boost/serialization/array.hpp2
-rw-r--r--boost/serialization/binary_object.hpp4
-rw-r--r--boost/serialization/collections_load_imp.hpp2
-rw-r--r--boost/serialization/detail/is_default_constructible.hpp14
-rw-r--r--boost/serialization/factory.hpp45
-rw-r--r--boost/serialization/optional.hpp55
-rw-r--r--boost/serialization/singleton.hpp76
-rw-r--r--boost/shared_array.hpp2
-rw-r--r--boost/shared_ptr.hpp2
-rw-r--r--boost/signals2/detail/auto_buffer.hpp21
-rw-r--r--boost/signals2/detail/slot_call_iterator.hpp4
-rw-r--r--boost/smart_ptr.hpp15
-rw-r--r--boost/smart_ptr/allocate_local_shared_array.hpp228
-rw-r--r--boost/smart_ptr/allocate_shared_array.hpp983
-rw-r--r--boost/smart_ptr/atomic_shared_ptr.hpp183
-rw-r--r--boost/smart_ptr/bad_weak_ptr.hpp6
-rw-r--r--boost/smart_ptr/detail/atomic_count_gcc.hpp2
-rw-r--r--boost/smart_ptr/detail/local_counted_base.hpp146
-rw-r--r--boost/smart_ptr/detail/local_sp_deleter.hpp91
-rw-r--r--boost/smart_ptr/detail/lwm_win32_cs.hpp28
-rw-r--r--boost/smart_ptr/detail/operator_bool.hpp12
-rw-r--r--boost/smart_ptr/detail/shared_count.hpp18
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp1
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_aix.hpp1
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_clang.hpp1
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp1
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp1
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp1
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp1
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp1
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp1
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp1
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_nt.hpp1
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_pt.hpp1
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp1
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_solaris.hpp1
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_spin.hpp1
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp1
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_sync.hpp1
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp1
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_w32.hpp1
-rw-r--r--boost/smart_ptr/detail/sp_counted_impl.hpp29
-rw-r--r--boost/smart_ptr/detail/sp_noexcept.hpp24
-rw-r--r--boost/smart_ptr/detail/yield_k.hpp2
-rw-r--r--boost/smart_ptr/enable_shared_from_this.hpp12
-rw-r--r--boost/smart_ptr/intrusive_ptr.hpp52
-rw-r--r--boost/smart_ptr/intrusive_ref_counter.hpp33
-rw-r--r--boost/smart_ptr/local_shared_ptr.hpp684
-rw-r--r--boost/smart_ptr/make_local_shared.hpp17
-rw-r--r--boost/smart_ptr/make_local_shared_array.hpp67
-rw-r--r--boost/smart_ptr/make_local_shared_object.hpp199
-rw-r--r--boost/smart_ptr/make_shared.hpp3
-rw-r--r--boost/smart_ptr/make_shared_object.hpp38
-rw-r--r--boost/smart_ptr/owner_less.hpp2
-rw-r--r--boost/smart_ptr/scoped_array.hpp23
-rw-r--r--boost/smart_ptr/scoped_ptr.hpp31
-rw-r--r--boost/smart_ptr/shared_array.hpp44
-rw-r--r--boost/smart_ptr/shared_ptr.hpp225
-rw-r--r--boost/smart_ptr/weak_ptr.hpp46
-rw-r--r--boost/spirit/home/classic/core/non_terminal/impl/grammar.ipp12
-rw-r--r--boost/spirit/home/classic/error_handling/exceptions.hpp1
-rw-r--r--boost/spirit/home/classic/phoenix/special_ops.hpp12
-rw-r--r--boost/spirit/home/classic/symbols/impl/tst.ipp6
-rw-r--r--boost/spirit/home/karma/auxiliary/lazy.hpp2
-rw-r--r--boost/spirit/home/karma/nonterminal/rule.hpp2
-rw-r--r--boost/spirit/home/karma/numeric/detail/numeric_utils.hpp5
-rw-r--r--boost/spirit/home/lex/lexer/lexertl/functor.hpp6
-rw-r--r--boost/spirit/home/lex/qi/plain_token.hpp2
-rw-r--r--boost/spirit/home/qi/detail/alternative_function.hpp5
-rw-r--r--boost/spirit/home/qi/detail/construct.hpp8
-rw-r--r--boost/spirit/home/qi/detail/expectation_failure.hpp34
-rw-r--r--boost/spirit/home/qi/directive.hpp1
-rw-r--r--boost/spirit/home/qi/directive/expect.hpp113
-rw-r--r--boost/spirit/home/qi/nonterminal/debug_handler.hpp2
-rw-r--r--boost/spirit/home/qi/numeric/detail/numeric_utils.hpp10
-rw-r--r--boost/spirit/home/qi/numeric/detail/real_impl.hpp13
-rw-r--r--boost/spirit/home/qi/operator/expect.hpp32
-rw-r--r--boost/spirit/home/support/attributes.hpp3
-rw-r--r--boost/spirit/home/support/common_terminals.hpp1
-rw-r--r--boost/spirit/home/support/detail/lexer/generator.hpp47
-rw-r--r--boost/spirit/home/support/detail/pow10.hpp1
-rw-r--r--boost/spirit/home/support/iterators/multi_pass.hpp8
-rw-r--r--boost/spirit/home/x3/auxiliary/attr.hpp8
-rw-r--r--boost/spirit/home/x3/auxiliary/eps.hpp2
-rw-r--r--boost/spirit/home/x3/char/char.hpp6
-rw-r--r--boost/spirit/home/x3/char/char_class.hpp2
-rw-r--r--boost/spirit/home/x3/char/char_set.hpp2
-rw-r--r--boost/spirit/home/x3/core/call.hpp2
-rw-r--r--boost/spirit/home/x3/core/detail/parse_into_container.hpp10
-rw-r--r--boost/spirit/home/x3/core/parser.hpp27
-rw-r--r--boost/spirit/home/x3/nonterminal/detail/rule.hpp16
-rw-r--r--boost/spirit/home/x3/nonterminal/rule.hpp10
-rw-r--r--boost/spirit/home/x3/numeric.hpp2
-rw-r--r--boost/spirit/home/x3/numeric/bool.hpp2
-rw-r--r--boost/spirit/home/x3/operator/detail/alternative.hpp2
-rw-r--r--boost/spirit/home/x3/string/literal_string.hpp6
-rw-r--r--boost/spirit/home/x3/string/symbols.hpp2
-rw-r--r--boost/spirit/home/x3/support/context.hpp6
-rw-r--r--boost/spirit/home/x3/support/traits/container_traits.hpp4
-rw-r--r--boost/spirit/include/qi_expect.hpp1
-rw-r--r--boost/spirit/include/version.hpp2
-rw-r--r--boost/stacktrace.hpp19
-rw-r--r--boost/stacktrace/detail/addr2line_impls.hpp225
-rw-r--r--boost/stacktrace/detail/collect_msvc.ipp33
-rw-r--r--boost/stacktrace/detail/collect_noop.ipp25
-rw-r--r--boost/stacktrace/detail/collect_unwind.ipp68
-rw-r--r--boost/stacktrace/detail/frame_decl.hpp159
-rw-r--r--boost/stacktrace/detail/frame_msvc.ipp392
-rw-r--r--boost/stacktrace/detail/frame_noop.ipp44
-rw-r--r--boost/stacktrace/detail/frame_unwind.ipp103
-rw-r--r--boost/stacktrace/detail/libbacktrace_impls.hpp173
-rw-r--r--boost/stacktrace/detail/location_from_symbol.hpp76
-rw-r--r--boost/stacktrace/detail/pop_options.pp12
-rw-r--r--boost/stacktrace/detail/push_options.pp31
-rw-r--r--boost/stacktrace/detail/safe_dump_noop.ipp37
-rw-r--r--boost/stacktrace/detail/safe_dump_posix.ipp58
-rw-r--r--boost/stacktrace/detail/safe_dump_win.ipp60
-rw-r--r--boost/stacktrace/detail/to_hex_array.hpp54
-rw-r--r--boost/stacktrace/detail/unwind_base_impls.hpp50
-rw-r--r--boost/stacktrace/detail/void_ptr_cast.hpp46
-rw-r--r--boost/stacktrace/frame.hpp67
-rw-r--r--boost/stacktrace/safe_dump_to.hpp218
-rw-r--r--boost/stacktrace/stacktrace.hpp414
-rw-r--r--boost/stacktrace/stacktrace_fwd.hpp28
-rw-r--r--boost/system/detail/error_code.ipp212
-rw-r--r--boost/system/detail/local_free_on_destruction.hpp4
-rw-r--r--boost/system/error_code.hpp293
-rw-r--r--boost/system/system_error.hpp8
-rw-r--r--boost/system/windows_error.hpp116
-rw-r--r--boost/test/data/monomorphic/collection.hpp2
-rw-r--r--boost/test/data/monomorphic/fwd.hpp4
-rw-r--r--boost/test/data/monomorphic/generate.hpp2
-rw-r--r--boost/test/data/monomorphic/grid.hpp2
-rw-r--r--boost/test/data/monomorphic/singleton.hpp2
-rw-r--r--boost/test/data/test_case.hpp1
-rw-r--r--boost/test/detail/fwd_decl.hpp1
-rw-r--r--boost/test/detail/global_typedef.hpp15
-rw-r--r--boost/test/execution_monitor.hpp1
-rw-r--r--boost/test/framework.hpp31
-rw-r--r--boost/test/impl/compiler_log_formatter.ipp16
-rw-r--r--boost/test/impl/execution_monitor.ipp6
-rw-r--r--boost/test/impl/framework.ipp210
-rw-r--r--boost/test/impl/junit_log_formatter.ipp274
-rw-r--r--boost/test/impl/results_collector.ipp6
-rw-r--r--boost/test/impl/test_framework_init_observer.ipp109
-rw-r--r--boost/test/impl/test_tools.ipp45
-rw-r--r--boost/test/impl/test_tree.ipp19
-rw-r--r--boost/test/impl/unit_test_log.ipp6
-rw-r--r--boost/test/impl/unit_test_monitor.ipp2
-rw-r--r--boost/test/impl/xml_log_formatter.ipp4
-rw-r--r--boost/test/included/test_exec_monitor.hpp1
-rw-r--r--boost/test/included/unit_test.hpp3
-rw-r--r--boost/test/output/compiler_log_formatter.hpp4
-rw-r--r--boost/test/output/junit_log_formatter.hpp4
-rw-r--r--boost/test/output/xml_log_formatter.hpp4
-rw-r--r--boost/test/progress_monitor.hpp2
-rw-r--r--boost/test/results_collector.hpp5
-rw-r--r--boost/test/test_framework_init_observer.hpp63
-rw-r--r--boost/test/tools/collection_comparison_op.hpp100
-rw-r--r--boost/test/tools/cstring_comparison_op.hpp11
-rw-r--r--boost/test/tools/fpc_op.hpp118
-rw-r--r--boost/test/tree/fixture.hpp93
-rw-r--r--boost/test/tree/global_fixture.hpp70
-rw-r--r--boost/test/tree/observer.hpp6
-rw-r--r--boost/test/unit_test_log.hpp2
-rw-r--r--boost/test/unit_test_log_formatter.hpp12
-rw-r--r--boost/test/unit_test_suite.hpp29
-rw-r--r--boost/test/utils/algorithm.hpp18
-rw-r--r--boost/test/utils/basic_cstring/basic_cstring.hpp13
-rw-r--r--boost/test/utils/basic_cstring/compare.hpp6
-rw-r--r--boost/test/utils/is_cstring.hpp41
-rw-r--r--boost/test/utils/is_forward_iterable.hpp88
-rw-r--r--boost/thread/concurrent_queues/sync_bounded_queue.hpp6
-rw-r--r--boost/thread/detail/config.hpp2
-rw-r--r--boost/thread/detail/thread.hpp26
-rw-r--r--boost/thread/future.hpp36
-rw-r--r--boost/thread/pthread/condition_variable.hpp26
-rw-r--r--boost/thread/pthread/pthread_mutex_scoped_lock.hpp24
-rw-r--r--boost/thread/pthread/thread_data.hpp15
-rw-r--r--boost/thread/win32/condition_variable.hpp81
-rw-r--r--boost/token_iterator.hpp7
-rw-r--r--boost/tr1/array.hpp86
-rw-r--r--boost/tr1/cmath.hpp267
-rw-r--r--boost/tr1/complex.hpp244
-rw-r--r--boost/tr1/detail/config.hpp173
-rw-r--r--boost/tr1/detail/config_all.hpp171
-rw-r--r--boost/tr1/detail/functor2iterator.hpp34
-rw-r--r--boost/tr1/detail/math_overloads.hpp58
-rw-r--r--boost/tr1/functional.hpp143
-rw-r--r--boost/tr1/memory.hpp72
-rw-r--r--boost/tr1/random.hpp586
-rw-r--r--boost/tr1/regex.hpp147
-rw-r--r--boost/tr1/tr1/algorithm27
-rw-r--r--boost/tr1/tr1/array34
-rw-r--r--boost/tr1/tr1/bcc32/array.h13
-rw-r--r--boost/tr1/tr1/bcc32/random.h13
-rw-r--r--boost/tr1/tr1/bcc32/regex.h13
-rw-r--r--boost/tr1/tr1/bcc32/tuple.h13
-rw-r--r--boost/tr1/tr1/bcc32/type_tra.h13
-rw-r--r--boost/tr1/tr1/bcc32/unordere.h15
-rw-r--r--boost/tr1/tr1/bitset27
-rw-r--r--boost/tr1/tr1/cmath41
-rw-r--r--boost/tr1/tr1/complex31
-rw-r--r--boost/tr1/tr1/deque27
-rw-r--r--boost/tr1/tr1/exception39
-rw-r--r--boost/tr1/tr1/fstream27
-rw-r--r--boost/tr1/tr1/functional30
-rw-r--r--boost/tr1/tr1/iomanip27
-rw-r--r--boost/tr1/tr1/ios27
-rw-r--r--boost/tr1/tr1/iostream27
-rw-r--r--boost/tr1/tr1/istream27
-rw-r--r--boost/tr1/tr1/iterator27
-rw-r--r--boost/tr1/tr1/limits27
-rw-r--r--boost/tr1/tr1/list27
-rw-r--r--boost/tr1/tr1/locale27
-rw-r--r--boost/tr1/tr1/map27
-rw-r--r--boost/tr1/tr1/memory31
-rw-r--r--boost/tr1/tr1/new35
-rw-r--r--boost/tr1/tr1/numeric27
-rw-r--r--boost/tr1/tr1/ostream27
-rw-r--r--boost/tr1/tr1/queue27
-rw-r--r--boost/tr1/tr1/random34
-rw-r--r--boost/tr1/tr1/regex22
-rw-r--r--boost/tr1/tr1/set27
-rw-r--r--boost/tr1/tr1/sstream27
-rw-r--r--boost/tr1/tr1/stack27
-rw-r--r--boost/tr1/tr1/stdexcept34
-rw-r--r--boost/tr1/tr1/streambuf27
-rw-r--r--boost/tr1/tr1/string27
-rw-r--r--boost/tr1/tr1/strstream29
-rw-r--r--boost/tr1/tr1/sun/algorithm.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/array.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/bcc32.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/bitset.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/cmath.SUNWCCh7
-rw-r--r--boost/tr1/tr1/sun/complex.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/deque.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/exception.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/fstream.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/functional.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/iomanip.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/ios.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/iostream.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/istream.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/iterator.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/limits.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/list.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/locale.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/map.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/memory.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/new.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/numeric.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/ostream.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/queue.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/random.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/regex.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/set.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/sstream.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/stack.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/stdexcept.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/streambuf.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/string.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/strstream.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/sun.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/tuple.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/type_traits.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/typeinfo.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/unordered_map.SUNWCCh7
-rw-r--r--boost/tr1/tr1/sun/unordered_set.SUNWCCh7
-rw-r--r--boost/tr1/tr1/sun/utility.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/valarray.SUNWCCh6
-rw-r--r--boost/tr1/tr1/sun/vector.SUNWCCh6
-rw-r--r--boost/tr1/tr1/tuple34
-rw-r--r--boost/tr1/tr1/type_traits43
-rw-r--r--boost/tr1/tr1/typeinfo27
-rw-r--r--boost/tr1/tr1/unordered_map34
-rw-r--r--boost/tr1/tr1/unordered_set34
-rw-r--r--boost/tr1/tr1/utility41
-rw-r--r--boost/tr1/tr1/valarray27
-rw-r--r--boost/tr1/tr1/vector27
-rw-r--r--boost/tr1/tuple.hpp82
-rw-r--r--boost/tr1/type_traits.hpp87
-rw-r--r--boost/tr1/unordered_map.hpp33
-rw-r--r--boost/tr1/unordered_set.hpp33
-rw-r--r--boost/tr1/utility.hpp121
-rw-r--r--boost/type_index/ctti_type_index.hpp1
-rw-r--r--boost/type_index/detail/compile_time_type_info.hpp16
-rw-r--r--boost/type_index/stl_type_index.hpp10
-rw-r--r--boost/type_index/type_index_facade.hpp3
-rw-r--r--boost/type_traits.hpp1
-rw-r--r--boost/type_traits/add_const.hpp6
-rw-r--r--boost/type_traits/add_cv.hpp6
-rw-r--r--boost/type_traits/add_lvalue_reference.hpp6
-rw-r--r--boost/type_traits/add_pointer.hpp6
-rw-r--r--boost/type_traits/add_reference.hpp7
-rw-r--r--boost/type_traits/add_rvalue_reference.hpp6
-rw-r--r--boost/type_traits/add_volatile.hpp6
-rw-r--r--boost/type_traits/conditional.hpp6
-rw-r--r--boost/type_traits/copy_cv.hpp6
-rw-r--r--boost/type_traits/decay.hpp6
-rw-r--r--boost/type_traits/floating_point_promotion.hpp6
-rw-r--r--boost/type_traits/integral_promotion.hpp6
-rw-r--r--boost/type_traits/make_signed.hpp6
-rw-r--r--boost/type_traits/make_unsigned.hpp6
-rw-r--r--boost/type_traits/promote.hpp6
-rw-r--r--boost/type_traits/remove_all_extents.hpp6
-rw-r--r--boost/type_traits/remove_bounds.hpp7
-rw-r--r--boost/type_traits/remove_const.hpp6
-rw-r--r--boost/type_traits/remove_cv.hpp5
-rw-r--r--boost/type_traits/remove_cv_ref.hpp30
-rw-r--r--boost/type_traits/remove_extent.hpp6
-rw-r--r--boost/type_traits/remove_pointer.hpp6
-rw-r--r--boost/type_traits/remove_reference.hpp5
-rw-r--r--boost/type_traits/remove_volatile.hpp5
-rw-r--r--boost/type_traits/type_identity.hpp7
-rw-r--r--boost/typeof/decltype.hpp34
-rw-r--r--boost/typeof/msvc/typeof_impl.hpp90
-rw-r--r--[-rwxr-xr-x]boost/typeof/native.hpp0
-rw-r--r--[-rwxr-xr-x]boost/typeof/register_fundamental.hpp3
-rw-r--r--boost/typeof/typeof.hpp37
-rw-r--r--boost/unordered/detail/fwd.hpp4
-rw-r--r--boost/unordered/detail/implementation.hpp2945
-rw-r--r--boost/unordered/detail/map.hpp49
-rw-r--r--boost/unordered/detail/set.hpp48
-rw-r--r--boost/unordered/unordered_map.hpp1469
-rw-r--r--boost/unordered/unordered_map_fwd.hpp9
-rw-r--r--boost/unordered/unordered_set.hpp966
-rw-r--r--boost/unordered/unordered_set_fwd.hpp6
-rw-r--r--boost/utility/result_of.hpp5
-rw-r--r--boost/utility/string_view.hpp60
-rw-r--r--boost/uuid/random_generator.hpp10
-rw-r--r--boost/variant/get.hpp59
-rw-r--r--boost/variant/polymorphic_get.hpp1
-rw-r--r--boost/variant/variant.hpp12
-rw-r--r--boost/version.hpp4
-rw-r--r--boost/wave/util/cpp_include_paths.hpp23
-rw-r--r--boost/wave/util/cpp_iterator.hpp2
-rw-r--r--boost/wave/util/flex_string.hpp2
-rw-r--r--boost/wave/wave_config.hpp9
-rw-r--r--boost/weak_ptr.hpp2
-rw-r--r--boost/xpressive/detail/utility/tracking_ptr.hpp4
-rw-r--r--boost/xpressive/match_results.hpp4
1229 files changed, 42981 insertions, 22934 deletions
diff --git a/boost/accumulators/numeric/functional.hpp b/boost/accumulators/numeric/functional.hpp
index d5d79f5c49..858decc199 100644
--- a/boost/accumulators/numeric/functional.hpp
+++ b/boost/accumulators/numeric/functional.hpp
@@ -99,11 +99,9 @@ namespace boost { namespace numeric
}; \
template<typename Arg, typename EnableIf> \
struct Name ## _base \
- : std::unary_function< \
- typename remove_const<Arg>::type \
- , typename result_of_ ## Name<Arg>::type \
- > \
{ \
+ typedef typename remove_const<Arg>::type argument_type; \
+ typedef typename result_of_ ## Name<Arg>::type result_type; \
typename result_of_ ## Name<Arg>::type operator ()(Arg &arg) const \
{ \
return Op arg; \
@@ -138,12 +136,10 @@ namespace boost { namespace numeric
}; \
template<typename Left, typename Right, typename EnableIf> \
struct Name ## _base \
- : std::binary_function< \
- typename remove_const<Left>::type \
- , typename remove_const<Right>::type \
- , typename result_of_ ## Name<Left, Right>::type \
- > \
{ \
+ typedef typename remove_const<Left>::type first_argument_type; \
+ typedef typename remove_const<Right>::type second_argument_type; \
+ typedef typename result_of_ ## Name<Left, Right>::type result_type; \
typename result_of_ ## Name<Left, Right>::type \
operator ()(Left &left, Right &right) const \
{ \
@@ -220,8 +216,11 @@ namespace boost { namespace numeric
{
template<typename Left, typename Right, typename EnableIf>
struct min_assign_base
- : std::binary_function<Left, Right, void>
{
+ typedef Left first_argument_type;
+ typedef Right second_argument_type;
+ typedef void result_type;
+
void operator ()(Left &left, Right &right) const
{
if(numeric::less(right, left))
@@ -233,8 +232,11 @@ namespace boost { namespace numeric
template<typename Left, typename Right, typename EnableIf>
struct max_assign_base
- : std::binary_function<Left, Right, void>
{
+ typedef Left first_argument_type;
+ typedef Right second_argument_type;
+ typedef void result_type;
+
void operator ()(Left &left, Right &right) const
{
if(numeric::greater(right, left))
@@ -258,8 +260,10 @@ namespace boost { namespace numeric
template<typename To, typename From, typename EnableIf>
struct promote_base
- : std::unary_function<From, To>
{
+ typedef From argument_type;
+ typedef To result_type;
+
To operator ()(From &from) const
{
return from;
@@ -268,8 +272,10 @@ namespace boost { namespace numeric
template<typename ToFrom>
struct promote_base<ToFrom, ToFrom, void>
- : std::unary_function<ToFrom, ToFrom>
{
+ typedef ToFrom argument_type;
+ typedef ToFrom result_type;
+
ToFrom &operator ()(ToFrom &tofrom)
{
return tofrom;
@@ -278,10 +284,12 @@ namespace boost { namespace numeric
template<typename Arg, typename EnableIf>
struct as_min_base
- : std::unary_function<Arg, typename remove_const<Arg>::type>
{
BOOST_STATIC_ASSERT(std::numeric_limits<typename remove_const<Arg>::type>::is_specialized);
+ typedef Arg argument_type;
+ typedef typename remove_const<Arg>::type result_type;
+
typename remove_const<Arg>::type operator ()(Arg &) const
{
return (std::numeric_limits<typename remove_const<Arg>::type>::min)();
@@ -290,10 +298,12 @@ namespace boost { namespace numeric
template<typename Arg>
struct as_min_base<Arg, typename enable_if<is_floating_point<Arg> >::type>
- : std::unary_function<Arg, typename remove_const<Arg>::type>
{
BOOST_STATIC_ASSERT(std::numeric_limits<typename remove_const<Arg>::type>::is_specialized);
+ typedef Arg argument_type;
+ typedef typename remove_const<Arg>::type result_type;
+
typename remove_const<Arg>::type operator ()(Arg &) const
{
return -(std::numeric_limits<typename remove_const<Arg>::type>::max)();
@@ -302,10 +312,12 @@ namespace boost { namespace numeric
template<typename Arg, typename EnableIf>
struct as_max_base
- : std::unary_function<Arg, typename remove_const<Arg>::type>
{
BOOST_STATIC_ASSERT(std::numeric_limits<typename remove_const<Arg>::type>::is_specialized);
+ typedef Arg argument_type;
+ typedef typename remove_const<Arg>::type result_type;
+
typename remove_const<Arg>::type operator ()(Arg &) const
{
return (std::numeric_limits<typename remove_const<Arg>::type>::max)();
@@ -314,8 +326,10 @@ namespace boost { namespace numeric
template<typename Arg, typename EnableIf>
struct as_zero_base
- : std::unary_function<Arg, typename remove_const<Arg>::type>
{
+ typedef Arg argument_type;
+ typedef typename remove_const<Arg>::type result_type;
+
typename remove_const<Arg>::type operator ()(Arg &) const
{
return numeric::zero<typename remove_const<Arg>::type>::value;
@@ -324,8 +338,10 @@ namespace boost { namespace numeric
template<typename Arg, typename EnableIf>
struct as_one_base
- : std::unary_function<Arg, typename remove_const<Arg>::type>
{
+ typedef Arg argument_type;
+ typedef typename remove_const<Arg>::type result_type;
+
typename remove_const<Arg>::type operator ()(Arg &) const
{
return numeric::one<typename remove_const<Arg>::type>::value;
diff --git a/boost/accumulators/numeric/functional/valarray.hpp b/boost/accumulators/numeric/functional/valarray.hpp
index c24b45859d..1996c75845 100644
--- a/boost/accumulators/numeric/functional/valarray.hpp
+++ b/boost/accumulators/numeric/functional/valarray.hpp
@@ -118,17 +118,9 @@ namespace boost { namespace numeric
#define BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(Name, Op) \
template<typename Left, typename Right> \
struct Name<Left, Right, std_valarray_tag, std_valarray_tag> \
- : std::binary_function< \
- Left \
- , Right \
- , std::valarray< \
- typename Name< \
- typename Left::value_type \
- , typename Right::value_type \
- >::result_type \
- > \
- > \
{ \
+ typedef Left first_argument_type; \
+ typedef Right second_argument_type; \
typedef typename Left::value_type left_value_type; \
typedef typename Right::value_type right_value_type; \
typedef \
@@ -145,14 +137,9 @@ namespace boost { namespace numeric
}; \
template<typename Left, typename Right> \
struct Name<Left, Right, std_valarray_tag, void> \
- : std::binary_function< \
- Left \
- , Right \
- , std::valarray< \
- typename Name<typename Left::value_type, Right>::result_type \
- > \
- > \
{ \
+ typedef Left first_argument_type; \
+ typedef Right second_argument_type; \
typedef typename Left::value_type left_value_type; \
typedef \
std::valarray< \
@@ -167,14 +154,9 @@ namespace boost { namespace numeric
}; \
template<typename Left, typename Right> \
struct Name<Left, Right, void, std_valarray_tag> \
- : std::binary_function< \
- Left \
- , Right \
- , std::valarray< \
- typename Name<Left, typename Right::value_type>::result_type \
- > \
- > \
{ \
+ typedef Left first_argument_type; \
+ typedef Right second_argument_type; \
typedef typename Right::value_type right_value_type; \
typedef \
std::valarray< \
@@ -200,8 +182,11 @@ namespace boost { namespace numeric
// element-wise min of std::valarray
template<typename Left, typename Right>
struct min_assign<Left, Right, std_valarray_tag, std_valarray_tag>
- : std::binary_function<Left, Right, void>
{
+ typedef Left first_argument_type;
+ typedef Right second_argument_type;
+ typedef void result_type;
+
void operator ()(Left &left, Right &right) const
{
BOOST_ASSERT(left.size() == right.size());
@@ -219,8 +204,11 @@ namespace boost { namespace numeric
// element-wise max of std::valarray
template<typename Left, typename Right>
struct max_assign<Left, Right, std_valarray_tag, std_valarray_tag>
- : std::binary_function<Left, Right, void>
{
+ typedef Left first_argument_type;
+ typedef Right second_argument_type;
+ typedef void result_type;
+
void operator ()(Left &left, Right &right) const
{
BOOST_ASSERT(left.size() == right.size());
@@ -247,8 +235,10 @@ namespace boost { namespace numeric
// promote
template<typename To, typename From>
struct promote<To, From, std_valarray_tag, std_valarray_tag>
- : std::unary_function<From, To>
{
+ typedef From argument_type;
+ typedef To result_type;
+
To operator ()(From &arr) const
{
typename remove_const<To>::type res(arr.size());
@@ -262,8 +252,10 @@ namespace boost { namespace numeric
template<typename ToFrom>
struct promote<ToFrom, ToFrom, std_valarray_tag, std_valarray_tag>
- : std::unary_function<ToFrom, ToFrom>
{
+ typedef ToFrom argument_type;
+ typedef ToFrom result_type;
+
ToFrom &operator ()(ToFrom &tofrom) const
{
return tofrom;
@@ -275,8 +267,10 @@ namespace boost { namespace numeric
// if(numeric::promote<bool>(a == b))
template<typename From>
struct promote<bool, From, void, std_valarray_tag>
- : std::unary_function<From, bool>
{
+ typedef From argument_type;
+ typedef bool result_type;
+
bool operator ()(From &arr) const
{
BOOST_MPL_ASSERT((is_same<bool, typename From::value_type>));
@@ -300,8 +294,10 @@ namespace boost { namespace numeric
// functional::as_min
template<typename T>
struct as_min<T, std_valarray_tag>
- : std::unary_function<T, typename remove_const<T>::type>
{
+ typedef T argument_type;
+ typedef typename remove_const<T>::type result_type;
+
typename remove_const<T>::type operator ()(T &arr) const
{
return 0 == arr.size()
@@ -314,8 +310,10 @@ namespace boost { namespace numeric
// functional::as_max
template<typename T>
struct as_max<T, std_valarray_tag>
- : std::unary_function<T, typename remove_const<T>::type>
{
+ typedef T argument_type;
+ typedef typename remove_const<T>::type result_type;
+
typename remove_const<T>::type operator ()(T &arr) const
{
return 0 == arr.size()
@@ -328,8 +326,10 @@ namespace boost { namespace numeric
// functional::as_zero
template<typename T>
struct as_zero<T, std_valarray_tag>
- : std::unary_function<T, typename remove_const<T>::type>
{
+ typedef T argument_type;
+ typedef typename remove_const<T>::type result_type;
+
typename remove_const<T>::type operator ()(T &arr) const
{
return 0 == arr.size()
@@ -342,8 +342,10 @@ namespace boost { namespace numeric
// functional::as_one
template<typename T>
struct as_one<T, std_valarray_tag>
- : std::unary_function<T, typename remove_const<T>::type>
{
+ typedef T argument_type;
+ typedef typename remove_const<T>::type result_type;
+
typename remove_const<T>::type operator ()(T &arr) const
{
return 0 == arr.size()
diff --git a/boost/accumulators/numeric/functional/vector.hpp b/boost/accumulators/numeric/functional/vector.hpp
index 8a68a3f303..4c2fbd8ada 100644
--- a/boost/accumulators/numeric/functional/vector.hpp
+++ b/boost/accumulators/numeric/functional/vector.hpp
@@ -195,8 +195,11 @@ namespace boost { namespace numeric
// element-wise min of std::vector
template<typename Left, typename Right>
struct min_assign<Left, Right, std_vector_tag, std_vector_tag>
- : std::binary_function<Left, Right, void>
{
+ typedef Left first_argument_type;
+ typedef Right second_argument_type;
+ typedef void result_type;
+
void operator ()(Left &left, Right &right) const
{
BOOST_ASSERT(left.size() == right.size());
@@ -214,8 +217,11 @@ namespace boost { namespace numeric
// element-wise max of std::vector
template<typename Left, typename Right>
struct max_assign<Left, Right, std_vector_tag, std_vector_tag>
- : std::binary_function<Left, Right, void>
{
+ typedef Left first_argument_type;
+ typedef Right second_argument_type;
+ typedef void result_type;
+
void operator ()(Left &left, Right &right) const
{
BOOST_ASSERT(left.size() == right.size());
@@ -242,8 +248,10 @@ namespace boost { namespace numeric
// promote
template<typename To, typename From>
struct promote<To, From, std_vector_tag, std_vector_tag>
- : std::unary_function<From, To>
{
+ typedef From argument_type;
+ typedef To result_type;
+
To operator ()(From &arr) const
{
typename remove_const<To>::type res(arr.size());
@@ -257,8 +265,10 @@ namespace boost { namespace numeric
template<typename ToFrom>
struct promote<ToFrom, ToFrom, std_vector_tag, std_vector_tag>
- : std::unary_function<ToFrom, ToFrom>
{
+ typedef ToFrom argument_type;
+ typedef ToFrom result_type;
+
ToFrom &operator ()(ToFrom &tofrom) const
{
return tofrom;
@@ -269,8 +279,10 @@ namespace boost { namespace numeric
// functional::as_min
template<typename T>
struct as_min<T, std_vector_tag>
- : std::unary_function<T, typename remove_const<T>::type>
{
+ typedef T argument_type;
+ typedef typename remove_const<T>::type result_type;
+
typename remove_const<T>::type operator ()(T &arr) const
{
return 0 == arr.size()
@@ -283,8 +295,10 @@ namespace boost { namespace numeric
// functional::as_max
template<typename T>
struct as_max<T, std_vector_tag>
- : std::unary_function<T, typename remove_const<T>::type>
{
+ typedef T argument_type;
+ typedef typename remove_const<T>::type result_type;
+
typename remove_const<T>::type operator ()(T &arr) const
{
return 0 == arr.size()
@@ -297,8 +311,10 @@ namespace boost { namespace numeric
// functional::as_zero
template<typename T>
struct as_zero<T, std_vector_tag>
- : std::unary_function<T, typename remove_const<T>::type>
{
+ typedef T argument_type;
+ typedef typename remove_const<T>::type result_type;
+
typename remove_const<T>::type operator ()(T &arr) const
{
return 0 == arr.size()
@@ -311,8 +327,10 @@ namespace boost { namespace numeric
// functional::as_one
template<typename T>
struct as_one<T, std_vector_tag>
- : std::unary_function<T, typename remove_const<T>::type>
{
+ typedef T argument_type;
+ typedef typename remove_const<T>::type result_type;
+
typename remove_const<T>::type operator ()(T &arr) const
{
return 0 == arr.size()
diff --git a/boost/accumulators/statistics/covariance.hpp b/boost/accumulators/statistics/covariance.hpp
index 73c92aebb5..b3030b9676 100644
--- a/boost/accumulators/statistics/covariance.hpp
+++ b/boost/accumulators/statistics/covariance.hpp
@@ -50,17 +50,9 @@ namespace boost { namespace numeric
template<typename Left, typename Right>
struct outer_product<Left, Right, std_vector_tag, std_vector_tag>
- : std::binary_function<
- Left
- , Right
- , ublas::matrix<
- typename functional::multiplies<
- typename Left::value_type
- , typename Right::value_type
- >::result_type
- >
- >
{
+ typedef Left first_argument_type;
+ typedef Right second_argument_type;
typedef
ublas::matrix<
typename functional::multiplies<
diff --git a/boost/accumulators/statistics/tail.hpp b/boost/accumulators/statistics/tail.hpp
index cc9267f9d4..be6cdee392 100644
--- a/boost/accumulators/statistics/tail.hpp
+++ b/boost/accumulators/statistics/tail.hpp
@@ -248,8 +248,11 @@ namespace impl
///////////////////////////////////////////////////////////////////////////////
//
struct indirect_cmp
- : std::binary_function<std::size_t, std::size_t, bool>
{
+ typedef std::size_t first_argument_type;
+ typedef std::size_t second_argument_type;
+ typedef bool result_type;
+
indirect_cmp(std::vector<Sample> const &s)
: samples(s)
{
diff --git a/boost/accumulators/statistics/tail_variate_means.hpp b/boost/accumulators/statistics/tail_variate_means.hpp
index d34d4abcd5..a97eab5648 100644
--- a/boost/accumulators/statistics/tail_variate_means.hpp
+++ b/boost/accumulators/statistics/tail_variate_means.hpp
@@ -118,7 +118,11 @@ namespace impl
this->tail_means_.begin()
, this->tail_means_.end()
, this->tail_means_.begin()
+#ifdef BOOST_NO_CXX98_BINDERS
+ , std::bind(std::divides<float_type>(), std::placeholders::_1, factor)
+#else
, std::bind2nd(std::divides<float_type>(), factor)
+#endif
);
}
else
diff --git a/boost/accumulators/statistics/times2_iterator.hpp b/boost/accumulators/statistics/times2_iterator.hpp
index d46dd042ef..dbd81af7cf 100644
--- a/boost/accumulators/statistics/times2_iterator.hpp
+++ b/boost/accumulators/statistics/times2_iterator.hpp
@@ -23,7 +23,11 @@ namespace boost { namespace accumulators
namespace detail
{
typedef transform_iterator<
+#ifdef BOOST_NO_CXX98_BINDERS
+ decltype(std::bind(std::multiplies<std::size_t>(), 2, std::placeholders::_1))
+#else
std::binder1st<std::multiplies<std::size_t> >
+#endif
, counting_iterator<std::size_t>
> times2_iterator;
@@ -31,7 +35,11 @@ namespace detail
{
return make_transform_iterator(
make_counting_iterator(i)
+#ifdef BOOST_NO_CXX98_BINDERS
+ , std::bind(std::multiplies<std::size_t>(), 2, std::placeholders::_1)
+#else
, std::bind1st(std::multiplies<std::size_t>(), 2)
+#endif
);
}
diff --git a/boost/accumulators/statistics/weighted_tail_variate_means.hpp b/boost/accumulators/statistics/weighted_tail_variate_means.hpp
index 2c9078335d..b1133109ed 100644
--- a/boost/accumulators/statistics/weighted_tail_variate_means.hpp
+++ b/boost/accumulators/statistics/weighted_tail_variate_means.hpp
@@ -169,7 +169,11 @@ namespace impl
this->tail_means_.begin()
, this->tail_means_.end()
, this->tail_means_.begin()
+#ifdef BOOST_NO_CXX98_BINDERS
+ , std::bind(numeric::functional::divides<typename array_type::value_type const, float_type const>(), std::placeholders::_1, factor)
+#else
, std::bind2nd(numeric::functional::divides<typename array_type::value_type const, float_type const>(), factor)
+#endif
);
return make_iterator_range(this->tail_means_);
diff --git a/boost/algorithm/cxx11/is_partitioned.hpp b/boost/algorithm/cxx11/is_partitioned.hpp
index cb6c71e33b..c0076b932b 100644
--- a/boost/algorithm/cxx11/is_partitioned.hpp
+++ b/boost/algorithm/cxx11/is_partitioned.hpp
@@ -18,7 +18,8 @@
namespace boost { namespace algorithm {
/// \fn is_partitioned ( InputIterator first, InputIterator last, UnaryPredicate p )
-/// \brief Tests to see if a sequence is partitioned according to a predicate
+/// \brief Tests to see if a sequence is partitioned according to a predicate.
+/// In other words, all the items in the sequence that satisfy the predicate are at the beginning of the sequence.
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
@@ -39,7 +40,8 @@ bool is_partitioned ( InputIterator first, InputIterator last, UnaryPredicate p
}
/// \fn is_partitioned ( const Range &r, UnaryPredicate p )
-/// \brief Generates an increasing sequence of values, and stores them in the input Range.
+/// \brief Tests to see if a sequence is partitioned according to a predicate.
+/// In other words, all the items in the sequence that satisfy the predicate are at the beginning of the sequence.
///
/// \param r The input range
/// \param p The predicate to test the values with
diff --git a/boost/algorithm/cxx14/equal.hpp b/boost/algorithm/cxx14/equal.hpp
index f1539f885c..9f97be1d62 100644
--- a/boost/algorithm/cxx14/equal.hpp
+++ b/boost/algorithm/cxx14/equal.hpp
@@ -13,7 +13,6 @@
#define BOOST_ALGORITHM_EQUAL_HPP
#include <algorithm> // for std::equal
-#include <functional> // for std::binary_function
#include <iterator>
namespace boost { namespace algorithm {
@@ -21,7 +20,7 @@ namespace boost { namespace algorithm {
namespace detail {
template <class T1, class T2>
- struct eq : public std::binary_function<T1, T2, bool> {
+ struct eq {
bool operator () ( const T1& v1, const T2& v2 ) const { return v1 == v2 ;}
};
diff --git a/boost/algorithm/cxx17/exclusive_scan.hpp b/boost/algorithm/cxx17/exclusive_scan.hpp
new file mode 100644
index 0000000000..03ecea52ec
--- /dev/null
+++ b/boost/algorithm/cxx17/exclusive_scan.hpp
@@ -0,0 +1,52 @@
+/*
+ Copyright (c) Marshall Clow 2017.
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
+*/
+
+/// \file exclusive_scan.hpp
+/// \brief ???
+/// \author Marshall Clow
+
+#ifndef BOOST_ALGORITHM_EXCLUSIVE_SCAN_HPP
+#define BOOST_ALGORITHM_EXCLUSIVE_SCAN_HPP
+
+#include <functional> // for std::plus
+#include <iterator> // for std::iterator_traits
+
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/value_type.hpp>
+
+namespace boost { namespace algorithm {
+
+template<class InputIterator, class OutputIterator, class T, class BinaryOperation>
+OutputIterator exclusive_scan(InputIterator first, InputIterator last,
+ OutputIterator result, T init, BinaryOperation bOp)
+{
+ if (first != last)
+ {
+ T saved = init;
+ do
+ {
+ init = bOp(init, *first);
+ *result = saved;
+ saved = init;
+ ++result;
+ } while (++first != last);
+ }
+ return result;
+}
+
+template<class InputIterator, class OutputIterator, class T>
+OutputIterator exclusive_scan(InputIterator first, InputIterator last,
+ OutputIterator result, T init)
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type VT;
+ return exclusive_scan(first, last, result, init, std::plus<VT>());
+}
+
+}} // namespace boost and algorithm
+
+#endif // BOOST_ALGORITHM_EXCLUSIVE_SCAN_HPP
diff --git a/boost/algorithm/cxx17/for_each_n.hpp b/boost/algorithm/cxx17/for_each_n.hpp
new file mode 100644
index 0000000000..b8134cc06a
--- /dev/null
+++ b/boost/algorithm/cxx17/for_each_n.hpp
@@ -0,0 +1,37 @@
+/*
+ Copyright (c) Marshall Clow 2017.
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
+*/
+
+/// \file for_each_n.hpp
+/// \brief Apply a functor to the elements of a sequence
+/// \author Marshall Clow
+
+#ifndef BOOST_ALGORITHM_FOR_EACH_N_HPP
+#define BOOST_ALGORITHM_FOR_EACH_N_HPP
+
+#include <utility> // for std::pair
+
+namespace boost { namespace algorithm {
+
+/// \fn for_each_n(InputIterator first, Size n, Function f);
+/// \return first + n
+///
+/// \param first The start of the first range.
+/// \param n One past the end of the first range.
+/// \param f A functor to apply to the elements of the sequence
+/// \note If f returns a result, the result is ignored.
+template<class InputIterator, class Size, class Function>
+InputIterator for_each_n(InputIterator first, Size n, Function f)
+{
+ for ( ; n > 0; --n, ++first )
+ f(*first);
+
+ return first;
+}
+
+}} // namespace boost and algorithm
+
+#endif // BOOST_ALGORITHM_FOR_EACH_N_HPP
diff --git a/boost/algorithm/cxx17/inclusive_scan.hpp b/boost/algorithm/cxx17/inclusive_scan.hpp
new file mode 100644
index 0000000000..cd015f100f
--- /dev/null
+++ b/boost/algorithm/cxx17/inclusive_scan.hpp
@@ -0,0 +1,60 @@
+/*
+ Copyright (c) Marshall Clow 2017.
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
+*/
+
+/// \file transform_reduce.hpp
+/// \brief Combine the (transformed) elements of a sequence (or two) into a single value.
+/// \author Marshall Clow
+
+#ifndef BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
+#define BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
+
+#include <functional> // for std::plus
+#include <iterator> // for std::iterator_traits
+
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/value_type.hpp>
+
+namespace boost { namespace algorithm {
+
+template<class InputIterator, class OutputIterator, class T, class BinaryOperation>
+OutputIterator inclusive_scan(InputIterator first, InputIterator last,
+ OutputIterator result, BinaryOperation bOp, T init)
+{
+ for (; first != last; ++first, (void) ++result) {
+ init = bOp(init, *first);
+ *result = init;
+ }
+ return result;
+}
+
+
+template<class InputIterator, class OutputIterator, class BinaryOperation>
+OutputIterator inclusive_scan(InputIterator first, InputIterator last,
+ OutputIterator result, BinaryOperation bOp)
+{
+ if (first != last) {
+ typename std::iterator_traits<InputIterator>::value_type init = *first;
+ *result++ = init;
+ if (++first != last)
+ return inclusive_scan(first, last, result, bOp, init);
+ }
+
+ return result;
+}
+
+template<class InputIterator, class OutputIterator>
+OutputIterator inclusive_scan(InputIterator first, InputIterator last,
+ OutputIterator result)
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type VT;
+ return inclusive_scan(first, last, result, std::plus<VT>());
+}
+
+}} // namespace boost and algorithm
+
+#endif // BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
diff --git a/boost/algorithm/cxx17/reduce.hpp b/boost/algorithm/cxx17/reduce.hpp
new file mode 100644
index 0000000000..f47695b53a
--- /dev/null
+++ b/boost/algorithm/cxx17/reduce.hpp
@@ -0,0 +1,72 @@
+/*
+ Copyright (c) Marshall Clow 2017.
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
+*/
+
+/// \file reduce.hpp
+/// \brief Combine the elements of a sequence into a single value
+/// \author Marshall Clow
+
+#ifndef BOOST_ALGORITHM_REDUCE_HPP
+#define BOOST_ALGORITHM_REDUCE_HPP
+
+#include <functional> // for std::plus
+#include <iterator> // for std::iterator_traits
+
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/value_type.hpp>
+
+namespace boost { namespace algorithm {
+
+template<class InputIterator, class T, class BinaryOperation>
+T reduce(InputIterator first, InputIterator last, T init, BinaryOperation bOp)
+{
+ ;
+ for (; first != last; ++first)
+ init = bOp(init, *first);
+ return init;
+}
+
+template<class InputIterator, class T>
+T reduce(InputIterator first, InputIterator last, T init)
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type VT;
+ return reduce(first, last, init, std::plus<VT>());
+}
+
+template<class InputIterator>
+typename std::iterator_traits<InputIterator>::value_type
+reduce(InputIterator first, InputIterator last)
+{
+ return reduce(first, last,
+ typename std::iterator_traits<InputIterator>::value_type());
+}
+
+template<class Range>
+typename boost::range_value<Range>::type
+reduce(const Range &r)
+{
+ return reduce(boost::begin(r), boost::end(r));
+}
+
+// Not sure that this won't be ambiguous (1)
+template<class Range, class T>
+T reduce(const Range &r, T init)
+{
+ return reduce(boost::begin (r), boost::end (r), init);
+}
+
+
+// Not sure that this won't be ambiguous (2)
+template<class Range, class T, class BinaryOperation>
+T reduce(const Range &r, T init, BinaryOperation bOp)
+{
+ return reduce(boost::begin(r), boost::end(r), init, bOp);
+}
+
+}} // namespace boost and algorithm
+
+#endif // BOOST_ALGORITHM_REDUCE_HPP
diff --git a/boost/algorithm/cxx17/transform_exclusive_scan.hpp b/boost/algorithm/cxx17/transform_exclusive_scan.hpp
new file mode 100644
index 0000000000..d3b4329a0a
--- /dev/null
+++ b/boost/algorithm/cxx17/transform_exclusive_scan.hpp
@@ -0,0 +1,46 @@
+/*
+ Copyright (c) Marshall Clow 2017.
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
+*/
+
+/// \file transform_exclusive_scan.hpp
+/// \brief ????
+/// \author Marshall Clow
+
+#ifndef BOOST_ALGORITHM_TRANSFORM_EXCLUSIVE_SCAN_HPP
+#define BOOST_ALGORITHM_TRANSFORM_EXCLUSIVE_SCAN_HPP
+
+#include <functional> // for std::plus
+#include <iterator> // for std::iterator_traits
+
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/value_type.hpp>
+
+namespace boost { namespace algorithm {
+
+template<class InputIterator, class OutputIterator, class T,
+ class BinaryOperation, class UnaryOperation>
+OutputIterator transform_exclusive_scan(InputIterator first, InputIterator last,
+ OutputIterator result, T init,
+ BinaryOperation bOp, UnaryOperation uOp)
+{
+ if (first != last)
+ {
+ T saved = init;
+ do
+ {
+ init = bOp(init, uOp(*first));
+ *result = saved;
+ saved = init;
+ ++result;
+ } while (++first != last);
+ }
+ return result;
+}
+
+}} // namespace boost and algorithm
+
+#endif // BOOST_ALGORITHM_TRANSFORM_EXCLUSIVE_SCAN_HPP
diff --git a/boost/algorithm/cxx17/transform_inclusive_scan.hpp b/boost/algorithm/cxx17/transform_inclusive_scan.hpp
new file mode 100644
index 0000000000..476c117f92
--- /dev/null
+++ b/boost/algorithm/cxx17/transform_inclusive_scan.hpp
@@ -0,0 +1,58 @@
+/*
+ Copyright (c) Marshall Clow 2017.
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
+*/
+
+/// \file transform_reduce.hpp
+/// \brief Combine the (transformed) elements of a sequence (or two) into a single value.
+/// \author Marshall Clow
+
+#ifndef BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
+#define BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
+
+#include <functional> // for std::plus
+#include <iterator> // for std::iterator_traits
+
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/value_type.hpp>
+
+namespace boost { namespace algorithm {
+
+template<class InputIterator, class OutputIterator,
+ class BinaryOperation, class UnaryOperation, class T>
+OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last,
+ OutputIterator result,
+ BinaryOperation bOp, UnaryOperation uOp,
+ T init)
+{
+ for (; first != last; ++first, (void) ++result) {
+ init = bOp(init, uOp(*first));
+ *result = init;
+ }
+
+ return result;
+}
+
+template<class InputIterator, class OutputIterator,
+ class BinaryOperation, class UnaryOperation>
+OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last,
+ OutputIterator result,
+ BinaryOperation bOp, UnaryOperation uOp)
+{
+ if (first != last) {
+ typename std::iterator_traits<InputIterator>::value_type init = uOp(*first);
+ *result++ = init;
+ if (++first != last)
+ return transform_inclusive_scan(first, last, result, bOp, uOp, init);
+ }
+
+ return result;
+}
+
+
+}} // namespace boost and algorithm
+
+#endif // BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
diff --git a/boost/algorithm/cxx17/transform_reduce.hpp b/boost/algorithm/cxx17/transform_reduce.hpp
new file mode 100644
index 0000000000..7ebde7d325
--- /dev/null
+++ b/boost/algorithm/cxx17/transform_reduce.hpp
@@ -0,0 +1,55 @@
+/*
+ Copyright (c) Marshall Clow 2017.
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
+*/
+
+/// \file transform_reduce.hpp
+/// \brief Combine the (transformed) elements of a sequence (or two) into a single value.
+/// \author Marshall Clow
+
+#ifndef BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
+#define BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
+
+#include <functional> // for std::plus
+#include <iterator> // for std::iterator_traits
+
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/value_type.hpp>
+
+namespace boost { namespace algorithm {
+
+template<class InputIterator1, class InputIterator2, class T,
+ class BinaryOperation1, class BinaryOperation2>
+T transform_reduce(InputIterator1 first1, InputIterator1 last1,
+ InputIterator2 first2, T init,
+ BinaryOperation1 bOp1, BinaryOperation2 bOp2)
+{
+ for (; first1 != last1; ++first1, (void) ++first2)
+ init = bOp1(init, bOp2(*first1, *first2));
+ return init;
+}
+
+template<class InputIterator, class T,
+ class BinaryOperation, class UnaryOperation>
+T transform_reduce(InputIterator first, InputIterator last,
+ T init, BinaryOperation bOp, UnaryOperation uOp)
+{
+ for (; first != last; ++first)
+ init = bOp(init, uOp(*first));
+ return init;
+}
+
+template<class InputIterator1, class InputIterator2, class T>
+T transform_reduce(InputIterator1 first1, InputIterator1 last1,
+ InputIterator2 first2, T init)
+{
+ return transform_reduce(first1, last1, first2, init,
+ std::plus<T>(), std::multiplies<T>());
+}
+
+}} // namespace boost and algorithm
+
+#endif // BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP
diff --git a/boost/algorithm/hex.hpp b/boost/algorithm/hex.hpp
index 739e89f2f0..b8335843a8 100644
--- a/boost/algorithm/hex.hpp
+++ b/boost/algorithm/hex.hpp
@@ -73,7 +73,7 @@ namespace detail {
else if ( c >= 'A' && c <= 'F' ) retval = c - 'A' + 10;
else if ( c >= 'a' && c <= 'f' ) retval = c - 'a' + 10;
else BOOST_THROW_EXCEPTION (non_hex_input() << bad_char (c));
- return retval;
+ return static_cast<char>(retval);
}
// My own iterator_traits class.
diff --git a/boost/algorithm/is_palindrome.hpp b/boost/algorithm/is_palindrome.hpp
index cc63e18075..09881109a3 100644
--- a/boost/algorithm/is_palindrome.hpp
+++ b/boost/algorithm/is_palindrome.hpp
@@ -35,7 +35,7 @@ namespace boost { namespace algorithm {
/// For other sequences function will return false.
/// Complexity: O(N).
template <typename BidirectionalIterator, typename Predicate>
-bool is_palindrome(BidirectionalIterator begin, BidirectionalIterator end, Predicate p )
+bool is_palindrome(BidirectionalIterator begin, BidirectionalIterator end, Predicate p)
{
if(begin == end)
{
@@ -63,7 +63,7 @@ bool is_palindrome(BidirectionalIterator begin, BidirectionalIterator end, Predi
/// \return true if the entire sequence is palindrome
///
/// \param begin The start of the input sequence
-/// \param end One past the end of the input sequence
+/// \param end One past the end of the input sequence
///
/// \note This function will return true for empty sequences and for palindromes.
/// For other sequences function will return false.
@@ -71,26 +71,8 @@ bool is_palindrome(BidirectionalIterator begin, BidirectionalIterator end, Predi
template <typename BidirectionalIterator>
bool is_palindrome(BidirectionalIterator begin, BidirectionalIterator end)
{
- if(begin == end)
- {
- return true;
- }
-
- --end;
- while(begin != end)
- {
- if(!(*begin == *end))
- {
- return false;
- }
- ++begin;
- if(begin == end)
- {
- break;
- }
- --end;
- }
- return true;
+ return is_palindrome(begin, end,
+ std::equal_to<typename std::iterator_traits<BidirectionalIterator>::value_type> ());
}
/// \fn is_palindrome ( const R& range )
@@ -122,7 +104,6 @@ bool is_palindrome(const R& range, Predicate p)
return is_palindrome(boost::begin(range), boost::end(range), p);
}
-
/// \fn is_palindrome ( const char* str )
/// \return true if the entire sequence is palindrome
///
@@ -138,7 +119,6 @@ bool is_palindrome(const char* str)
return is_palindrome(str, str + strlen(str));
}
-
/// \fn is_palindrome ( const char* str, Predicate p )
/// \return true if the entire sequence is palindrome
///
@@ -155,7 +135,6 @@ bool is_palindrome(const char* str, Predicate p)
return true;
return is_palindrome(str, str + strlen(str), p);
}
-
}}
#endif // BOOST_ALGORITHM_IS_PALINDROME_HPP
diff --git a/boost/algorithm/is_partitioned_until.hpp b/boost/algorithm/is_partitioned_until.hpp
new file mode 100644
index 0000000000..42683e1d8e
--- /dev/null
+++ b/boost/algorithm/is_partitioned_until.hpp
@@ -0,0 +1,63 @@
+/*
+ Copyright (c) Alexander Zaitsev <zamazan4ik@gmail.by>, 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)
+*/
+
+/// \file is_partitioned_until.hpp
+/// \brief Tell if a sequence is partitioned
+/// \author Alexander Zaitsev
+
+#ifndef BOOST_ALGORITHM_IS_PARTITIONED_UNTIL_HPP
+#define BOOST_ALGORITHM_IS_PARTITIONED_UNTIL_HPP
+
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+
+namespace boost { namespace algorithm {
+
+/// \fn is_partitioned_until ( InputIterator first, InputIterator last, UnaryPredicate p )
+/// \brief Tests to see if a sequence is partitioned according to a predicate.
+/// In other words, all the items in the sequence that satisfy the predicate are at the beginning of the sequence.
+///
+/// \param first The start of the input sequence
+/// \param last One past the end of the input sequence
+/// \param p The predicate to test the values with
+///
+/// \note Returns the first iterator 'it' in the sequence [first, last) for which is_partitioned(first, it, p) is false.
+/// Returns last if the entire sequence is partitioned.
+/// Complexity: O(N).
+template <typename InputIterator, typename UnaryPredicate>
+InputIterator is_partitioned_until ( InputIterator first, InputIterator last, UnaryPredicate p )
+{
+// Run through the part that satisfy the predicate
+ for ( ; first != last; ++first )
+ if ( !p (*first))
+ break;
+// Now the part that does not satisfy the predicate
+ for ( ; first != last; ++first )
+ if ( p (*first))
+ return first;
+ return last;
+}
+
+/// \fn is_partitioned_until ( const Range &r, UnaryPredicate p )
+/// \brief Tests to see if a sequence is partitioned according to a predicate.
+/// In other words, all the items in the sequence that satisfy the predicate are at the beginning of the sequence.
+///
+/// \param r The input range
+/// \param p The predicate to test the values with
+///
+/// \note Returns the first iterator 'it' in the sequence [first, last) for which is_partitioned(first, it, p) is false.
+/// Returns last if the entire sequence is partitioned.
+/// Complexity: O(N).
+template <typename Range, typename UnaryPredicate>
+typename boost::range_iterator<const Range>::type is_partitioned_until ( const Range &r, UnaryPredicate p )
+{
+ return boost::algorithm::is_partitioned_until (boost::begin(r), boost::end(r), p);
+}
+
+}}
+
+#endif // BOOST_ALGORITHM_IS_PARTITIONED_UNTIL_HPP
diff --git a/boost/algorithm/searching/boyer_moore.hpp b/boost/algorithm/searching/boyer_moore.hpp
index 65a809dd4f..192d4dec25 100644
--- a/boost/algorithm/searching/boyer_moore.hpp
+++ b/boost/algorithm/searching/boyer_moore.hpp
@@ -152,8 +152,8 @@ Requirements:
template<typename Iter, typename Container>
- void compute_bm_prefix ( Iter pat_first, Iter pat_last, Container &prefix ) {
- const std::size_t count = std::distance ( pat_first, pat_last );
+ void compute_bm_prefix ( Iter first, Iter last, Container &prefix ) {
+ const std::size_t count = std::distance ( first, last );
BOOST_ASSERT ( count > 0 );
BOOST_ASSERT ( prefix.size () == count );
@@ -161,26 +161,26 @@ Requirements:
std::size_t k = 0;
for ( std::size_t i = 1; i < count; ++i ) {
BOOST_ASSERT ( k < count );
- while ( k > 0 && ( pat_first[k] != pat_first[i] )) {
+ while ( k > 0 && ( first[k] != first[i] )) {
BOOST_ASSERT ( k < count );
k = prefix [ k - 1 ];
}
- if ( pat_first[k] == pat_first[i] )
+ if ( first[k] == first[i] )
k++;
prefix [ i ] = k;
}
}
- void build_suffix_table ( patIter pat_first, patIter pat_last ) {
- const std::size_t count = (std::size_t) std::distance ( pat_first, pat_last );
+ void build_suffix_table ( patIter first, patIter last ) {
+ const std::size_t count = (std::size_t) std::distance ( first, last );
if ( count > 0 ) { // empty pattern
std::vector<typename std::iterator_traits<patIter>::value_type> reversed(count);
- (void) std::reverse_copy ( pat_first, pat_last, reversed.begin ());
+ (void) std::reverse_copy ( first, last, reversed.begin ());
std::vector<difference_type> prefix (count);
- compute_bm_prefix ( pat_first, pat_last, prefix );
+ compute_bm_prefix ( first, last, prefix );
std::vector<difference_type> prefix_reversed (count);
compute_bm_prefix ( reversed.begin (), reversed.end (), prefix_reversed );
diff --git a/boost/algorithm/searching/knuth_morris_pratt.hpp b/boost/algorithm/searching/knuth_morris_pratt.hpp
index c890c9cac0..5b5b64a729 100644
--- a/boost/algorithm/searching/knuth_morris_pratt.hpp
+++ b/boost/algorithm/searching/knuth_morris_pratt.hpp
@@ -155,9 +155,9 @@ namespace boost { namespace algorithm {
void preKmp ( patIter first, patIter last ) {
- const /*std::size_t*/ int count = std::distance ( first, last );
+ const difference_type count = std::distance ( first, last );
- int i, j;
+ difference_type i, j;
i = 0;
j = skip_[0] = -1;
@@ -177,7 +177,7 @@ namespace boost { namespace algorithm {
void init_skip_table ( patIter first, patIter last ) {
const difference_type count = std::distance ( first, last );
- int j;
+ difference_type j;
skip_ [ 0 ] = -1;
for ( int i = 1; i <= count; ++i ) {
j = skip_ [ i - 1 ];
diff --git a/boost/algorithm/string/detail/case_conv.hpp b/boost/algorithm/string/detail/case_conv.hpp
index 42621c74f0..233912ca0f 100644
--- a/boost/algorithm/string/detail/case_conv.hpp
+++ b/boost/algorithm/string/detail/case_conv.hpp
@@ -30,8 +30,10 @@ namespace boost {
// a tolower functor
template<typename CharT>
- struct to_lowerF : public std::unary_function<CharT, CharT>
+ struct to_lowerF
{
+ typedef CharT argument_type;
+ typedef CharT result_type;
// Constructor
to_lowerF( const std::locale& Loc ) : m_Loc( &Loc ) {}
@@ -50,8 +52,10 @@ namespace boost {
// a toupper functor
template<typename CharT>
- struct to_upperF : public std::unary_function<CharT, CharT>
+ struct to_upperF
{
+ typedef CharT argument_type;
+ typedef CharT result_type;
// Constructor
to_upperF( const std::locale& Loc ) : m_Loc( &Loc ) {}
diff --git a/boost/algorithm/string/detail/find_iterator.hpp b/boost/algorithm/string/detail/find_iterator.hpp
index 9b78a0f7e1..4f90a98fc0 100644
--- a/boost/algorithm/string/detail/find_iterator.hpp
+++ b/boost/algorithm/string/detail/find_iterator.hpp
@@ -40,7 +40,7 @@ namespace boost {
// Protected construction/destruction
// Default constructor
- find_iterator_base() {};
+ find_iterator_base() {}
// Copy construction
find_iterator_base( const find_iterator_base& Other ) :
m_Finder(Other.m_Finder) {}
diff --git a/boost/algorithm/string/detail/util.hpp b/boost/algorithm/string/detail/util.hpp
index cf4a8b1c8c..7844b6723c 100644
--- a/boost/algorithm/string/detail/util.hpp
+++ b/boost/algorithm/string/detail/util.hpp
@@ -89,9 +89,10 @@ namespace boost {
template<
typename SeqT,
typename IteratorT=BOOST_STRING_TYPENAME SeqT::const_iterator >
- struct copy_iterator_rangeF :
- public std::unary_function< iterator_range<IteratorT>, SeqT >
+ struct copy_iterator_rangeF
{
+ typedef iterator_range<IteratorT> argument_type;
+ typedef SeqT result_type;
SeqT operator()( const iterator_range<IteratorT>& Range ) const
{
return copy_range<SeqT>(Range);
diff --git a/boost/align/aligned_allocator.hpp b/boost/align/aligned_allocator.hpp
index 6d0f788952..6176bc27c0 100644
--- a/boost/align/aligned_allocator.hpp
+++ b/boost/align/aligned_allocator.hpp
@@ -28,8 +28,7 @@ namespace alignment {
template<class T, std::size_t Alignment>
class aligned_allocator {
- BOOST_STATIC_ASSERT(detail::
- is_alignment_constant<Alignment>::value);
+ BOOST_STATIC_ASSERT(detail::is_alignment_constant<Alignment>::value);
public:
typedef T value_type;
@@ -124,8 +123,7 @@ public:
template<std::size_t Alignment>
class aligned_allocator<void, Alignment> {
- BOOST_STATIC_ASSERT(detail::
- is_alignment_constant<Alignment>::value);
+ BOOST_STATIC_ASSERT(detail::is_alignment_constant<Alignment>::value);
public:
typedef void value_type;
diff --git a/boost/align/aligned_allocator_adaptor.hpp b/boost/align/aligned_allocator_adaptor.hpp
index 8905c215d3..c9fae1cf20 100644
--- a/boost/align/aligned_allocator_adaptor.hpp
+++ b/boost/align/aligned_allocator_adaptor.hpp
@@ -8,13 +8,13 @@ Distributed under the Boost Software License, Version 1.0.
#ifndef BOOST_ALIGN_ALIGNED_ALLOCATOR_ADAPTOR_HPP
#define BOOST_ALIGN_ALIGNED_ALLOCATOR_ADAPTOR_HPP
-#include <boost/align/detail/addressof.hpp>
#include <boost/align/detail/is_alignment_constant.hpp>
#include <boost/align/detail/max_align.hpp>
#include <boost/align/detail/max_size.hpp>
#include <boost/align/align.hpp>
#include <boost/align/aligned_allocator_adaptor_forward.hpp>
#include <boost/align/alignment_of.hpp>
+#include <boost/core/pointer_traits.hpp>
#include <boost/static_assert.hpp>
#include <new>
@@ -32,39 +32,25 @@ namespace alignment {
template<class Allocator, std::size_t Alignment>
class aligned_allocator_adaptor
: public Allocator {
- BOOST_STATIC_ASSERT(detail::
- is_alignment_constant<Alignment>::value);
+ BOOST_STATIC_ASSERT(detail::is_alignment_constant<Alignment>::value);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
typedef std::allocator_traits<Allocator> traits;
-
- typedef typename traits::
- template rebind_alloc<char> char_alloc;
-
- typedef typename traits::
- template rebind_traits<char> char_traits;
-
+ typedef typename traits::template rebind_alloc<char> char_alloc;
+ typedef typename traits::template rebind_traits<char> char_traits;
typedef typename char_traits::pointer char_ptr;
#else
- typedef typename Allocator::
- template rebind<char>::other char_alloc;
-
+ typedef typename Allocator::template rebind<char>::other char_alloc;
typedef typename char_alloc::pointer char_ptr;
#endif
public:
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
- typedef typename traits::value_type value_type;
- typedef typename traits::size_type size_type;
-#else
typedef typename Allocator::value_type value_type;
- typedef typename Allocator::size_type size_type;
-#endif
-
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef void* void_pointer;
typedef const void* const_void_pointer;
+ typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
private:
@@ -77,11 +63,11 @@ public:
template<class U>
struct rebind {
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
- typedef aligned_allocator_adaptor<typename traits::
- template rebind_alloc<U>, Alignment> other;
+ typedef aligned_allocator_adaptor<typename traits::template
+ rebind_alloc<U>, Alignment> other;
#else
- typedef aligned_allocator_adaptor<typename Allocator::
- template rebind<U>::other, Alignment> other;
+ typedef aligned_allocator_adaptor<typename Allocator::template
+ rebind<U>::other, Alignment> other;
#endif
};
@@ -120,10 +106,9 @@ public:
std::size_t n = s + min_align - 1;
char_alloc a(base());
char_ptr p = a.allocate(sizeof p + n);
- void* r = detail::addressof(*p) + sizeof p;
+ void* r = boost::pointer_traits<char_ptr>::to_address(p) + sizeof p;
(void)align(min_align, s, r, n);
- ::new(static_cast<void*>(static_cast<char_ptr*>(r)
- - 1)) char_ptr(p);
+ ::new(static_cast<void*>(static_cast<char_ptr*>(r) - 1)) char_ptr(p);
return static_cast<pointer>(r);
}
@@ -140,10 +125,9 @@ public:
#else
char_ptr p = a.allocate(sizeof p + n, h);
#endif
- void* r = detail::addressof(*p) + sizeof p;
+ void* r = boost::pointer_traits<char_ptr>::to_address(p) + sizeof p;
(void)align(min_align, s, r, n);
- ::new(static_cast<void*>(static_cast<char_ptr*>(r)
- - 1)) char_ptr(p);
+ ::new(static_cast<void*>(static_cast<char_ptr*>(r) - 1)) char_ptr(p);
return static_cast<pointer>(r);
}
@@ -152,8 +136,7 @@ public:
char_ptr r = *p;
p->~char_ptr();
char_alloc a(base());
- a.deallocate(r, sizeof r + size * sizeof(value_type) +
- min_align - 1);
+ a.deallocate(r, sizeof r + size * sizeof(value_type) + min_align - 1);
}
};
diff --git a/boost/align/detail/align.hpp b/boost/align/detail/align.hpp
index a58dcea747..905940ad77 100644
--- a/boost/align/detail/align.hpp
+++ b/boost/align/detail/align.hpp
@@ -20,8 +20,8 @@ align(std::size_t alignment, std::size_t size, void*& ptr,
{
BOOST_ASSERT(detail::is_alignment(alignment));
if (size <= space) {
- char* p = reinterpret_cast<char*>((reinterpret_cast<std::
- size_t>(ptr) + alignment - 1) & ~(alignment - 1));
+ char* p = reinterpret_cast<char*>(~(alignment - 1) &
+ (reinterpret_cast<std::size_t>(ptr) + alignment - 1));
std::size_t n = space - (p - static_cast<char*>(ptr));
if (size <= n) {
ptr = p;
diff --git a/boost/align/detail/align_down.hpp b/boost/align/detail/align_down.hpp
index 9a8c358c41..de3c80d06d 100644
--- a/boost/align/detail/align_down.hpp
+++ b/boost/align/detail/align_down.hpp
@@ -18,8 +18,8 @@ inline void*
align_down(void* ptr, std::size_t alignment) BOOST_NOEXCEPT
{
BOOST_ASSERT(detail::is_alignment(alignment));
- return reinterpret_cast<void*>(reinterpret_cast<std::
- size_t>(ptr) & ~(alignment - 1));
+ return reinterpret_cast<void*>(~(alignment - 1) &
+ reinterpret_cast<std::size_t>(ptr));
}
} /* alignment */
diff --git a/boost/align/detail/align_up.hpp b/boost/align/detail/align_up.hpp
index 86686da6ae..ac11f8964f 100644
--- a/boost/align/detail/align_up.hpp
+++ b/boost/align/detail/align_up.hpp
@@ -18,8 +18,8 @@ inline void*
align_up(void* ptr, std::size_t alignment) BOOST_NOEXCEPT
{
BOOST_ASSERT(detail::is_alignment(alignment));
- return reinterpret_cast<void*>((reinterpret_cast<std::
- size_t>(ptr) + alignment - 1) & ~(alignment - 1));
+ return reinterpret_cast<void*>(~(alignment - 1) &
+ (reinterpret_cast<std::size_t>(ptr) + alignment - 1));
}
} /* alignment */
diff --git a/boost/align/detail/alignment_of_msvc.hpp b/boost/align/detail/alignment_of_msvc.hpp
index 1526c7c296..440b840db4 100644
--- a/boost/align/detail/alignment_of_msvc.hpp
+++ b/boost/align/detail/alignment_of_msvc.hpp
@@ -23,8 +23,7 @@ struct offset_value {
template<class T>
struct alignment_of
- : min_size<sizeof(T),
- sizeof(offset_value<T>) - (sizeof(T) << 1)> { };
+ : min_size<sizeof(T), sizeof(offset_value<T>) - (sizeof(T) << 1)> { };
} /* detail */
} /* alignment */
diff --git a/boost/align/detail/is_alignment.hpp b/boost/align/detail/is_alignment.hpp
index 8bedba19c3..542fbe4694 100644
--- a/boost/align/detail/is_alignment.hpp
+++ b/boost/align/detail/is_alignment.hpp
@@ -4,7 +4,6 @@ Copyright 2014 Glen Joseph Fernandes
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
-
*/
#ifndef BOOST_ALIGN_DETAIL_IS_ALIGNMENT_HPP
#define BOOST_ALIGN_DETAIL_IS_ALIGNMENT_HPP
diff --git a/boost/archive/basic_text_iarchive.hpp b/boost/archive/basic_text_iarchive.hpp
index 583041d8b4..48a646cc1f 100644
--- a/boost/archive/basic_text_iarchive.hpp
+++ b/boost/archive/basic_text_iarchive.hpp
@@ -21,7 +21,7 @@
//
// note the fact that on libraries without wide characters, ostream is
// is not a specialization of basic_ostream which in fact is not defined
-// in such cases. So we can't use basic_ostream<IStream::char_type> but rather
+// in such cases. So we can't use basic_istream<IStream::char_type> but rather
// use two template parameters
#include <boost/config.hpp>
diff --git a/boost/archive/codecvt_null.hpp b/boost/archive/codecvt_null.hpp
index 9cc9e5729d..7bce2b9b32 100644
--- a/boost/archive/codecvt_null.hpp
+++ b/boost/archive/codecvt_null.hpp
@@ -18,8 +18,11 @@
#include <locale>
#include <cstddef> // NULL, size_t
+#ifndef BOOST_NO_CWCHAR
#include <cwchar> // for mbstate_t
+#endif
#include <boost/config.hpp>
+#include <boost/serialization/force_include.hpp>
#include <boost/archive/detail/auto_link_archive.hpp>
#include <boost/archive/detail/abi_prefix.hpp> // must be the last header
@@ -62,7 +65,7 @@ public:
template<>
class BOOST_SYMBOL_VISIBLE codecvt_null<wchar_t> : public std::codecvt<wchar_t, char, std::mbstate_t>
{
- virtual BOOST_WARCHIVE_DECL std::codecvt_base::result
+ virtual BOOST_WARCHIVE_DECL BOOST_DLLEXPORT std::codecvt_base::result
do_out(
std::mbstate_t & state,
const wchar_t * first1,
@@ -71,8 +74,8 @@ class BOOST_SYMBOL_VISIBLE codecvt_null<wchar_t> : public std::codecvt<wchar_t,
char * first2,
char * last2,
char * & next2
- ) const;
- virtual BOOST_WARCHIVE_DECL std::codecvt_base::result
+ ) const BOOST_USED;
+ virtual BOOST_WARCHIVE_DECL BOOST_DLLEXPORT std::codecvt_base::result
do_in(
std::mbstate_t & state,
const char * first1,
@@ -81,7 +84,7 @@ class BOOST_SYMBOL_VISIBLE codecvt_null<wchar_t> : public std::codecvt<wchar_t,
wchar_t * first2,
wchar_t * last2,
wchar_t * & next2
- ) const;
+ ) const BOOST_USED;
virtual int do_encoding( ) const throw( ){
return sizeof(wchar_t) / sizeof(char);
}
@@ -89,7 +92,7 @@ class BOOST_SYMBOL_VISIBLE codecvt_null<wchar_t> : public std::codecvt<wchar_t,
return do_encoding();
}
public:
- explicit codecvt_null(std::size_t no_locale_manage = 0) :
+ BOOST_DLLEXPORT explicit codecvt_null(std::size_t no_locale_manage = 0) :
std::codecvt<wchar_t, char, std::mbstate_t>(no_locale_manage)
{}
virtual ~codecvt_null(){};
diff --git a/boost/archive/detail/iserializer.hpp b/boost/archive/detail/iserializer.hpp
index 6e02eec7c4..193e98a82e 100644
--- a/boost/archive/detail/iserializer.hpp
+++ b/boost/archive/detail/iserializer.hpp
@@ -605,7 +605,7 @@ template<class Archive, class T>
inline void load(Archive & ar, T &t){
// if this assertion trips. It means we're trying to load a
// const object with a compiler that doesn't have correct
- // funtion template ordering. On other compilers, this is
+ // function template ordering. On other compilers, this is
// handled below.
detail::check_const_loading< T >();
typedef
diff --git a/boost/archive/impl/archive_serializer_map.ipp b/boost/archive/impl/archive_serializer_map.ipp
index 8dabf0d08f..7f163ec407 100644
--- a/boost/archive/impl/archive_serializer_map.ipp
+++ b/boost/archive/impl/archive_serializer_map.ipp
@@ -47,6 +47,10 @@ archive_serializer_map<Archive>::insert(const basic_serializer * bs){
template<class Archive>
BOOST_ARCHIVE_OR_WARCHIVE_DECL void
archive_serializer_map<Archive>::erase(const basic_serializer * bs){
+ BOOST_ASSERT(! boost::serialization::singleton<
+ extra_detail::map<Archive>
+ >::is_destroyed()
+ );
if(boost::serialization::singleton<
extra_detail::map<Archive>
>::is_destroyed())
diff --git a/boost/archive/impl/basic_binary_iprimitive.ipp b/boost/archive/impl/basic_binary_iprimitive.ipp
index 7082b003e7..bbe933ccf6 100644
--- a/boost/archive/impl/basic_binary_iprimitive.ipp
+++ b/boost/archive/impl/basic_binary_iprimitive.ipp
@@ -84,6 +84,7 @@ basic_binary_iprimitive<Archive, Elem, Tr>::init()
);
}
+#ifndef BOOST_NO_CWCHAR
template<class Archive, class Elem, class Tr>
BOOST_ARCHIVE_OR_WARCHIVE_DECL void
basic_binary_iprimitive<Archive, Elem, Tr>::load(wchar_t * ws)
@@ -93,6 +94,7 @@ basic_binary_iprimitive<Archive, Elem, Tr>::load(wchar_t * ws)
load_binary(ws, l * sizeof(wchar_t) / sizeof(char));
ws[l] = L'\0';
}
+#endif
template<class Archive, class Elem, class Tr>
BOOST_ARCHIVE_OR_WARCHIVE_DECL void
@@ -110,7 +112,6 @@ basic_binary_iprimitive<Archive, Elem, Tr>::load(std::string & s)
load_binary(&(*s.begin()), l);
}
-#ifndef BOOST_NO_CWCHAR
template<class Archive, class Elem, class Tr>
BOOST_ARCHIVE_OR_WARCHIVE_DECL void
basic_binary_iprimitive<Archive, Elem, Tr>::load(char * s)
@@ -120,7 +121,6 @@ basic_binary_iprimitive<Archive, Elem, Tr>::load(char * s)
load_binary(s, l);
s[l] = '\0';
}
-#endif
#ifndef BOOST_NO_STD_WSTRING
template<class Archive, class Elem, class Tr>
diff --git a/boost/archive/impl/basic_binary_oprimitive.ipp b/boost/archive/impl/basic_binary_oprimitive.ipp
index 130831e4fb..7b042173a4 100644
--- a/boost/archive/impl/basic_binary_oprimitive.ipp
+++ b/boost/archive/impl/basic_binary_oprimitive.ipp
@@ -71,6 +71,7 @@ basic_binary_oprimitive<Archive, Elem, Tr>::save(const std::string &s)
}
#ifndef BOOST_NO_CWCHAR
+#ifndef BOOST_NO_INTRINSIC_WCHAR_T
template<class Archive, class Elem, class Tr>
BOOST_ARCHIVE_OR_WARCHIVE_DECL void
basic_binary_oprimitive<Archive, Elem, Tr>::save(const wchar_t * ws)
@@ -91,6 +92,7 @@ basic_binary_oprimitive<Archive, Elem, Tr>::save(const std::wstring &ws)
save_binary(ws.data(), l * sizeof(wchar_t) / sizeof(char));
}
#endif
+#endif // BOOST_NO_CWCHAR
template<class Archive, class Elem, class Tr>
BOOST_ARCHIVE_OR_WARCHIVE_DECL
diff --git a/boost/archive/impl/text_wiarchive_impl.ipp b/boost/archive/impl/text_wiarchive_impl.ipp
index 12af2b9f12..e85625ac32 100644
--- a/boost/archive/impl/text_wiarchive_impl.ipp
+++ b/boost/archive/impl/text_wiarchive_impl.ipp
@@ -56,7 +56,7 @@ text_wiarchive_impl<Archive>::load(std::string &s)
s.resize(0);
s.reserve(size);
while(size-- > 0){
- int x = is.narrow(is.get(), '\0');
+ char x = is.narrow(is.get(), '\0');
s += x;
}
}
diff --git a/boost/archive/impl/xml_woarchive_impl.ipp b/boost/archive/impl/xml_woarchive_impl.ipp
index 58f92c9d92..01b1a052d5 100644
--- a/boost/archive/impl/xml_woarchive_impl.ipp
+++ b/boost/archive/impl/xml_woarchive_impl.ipp
@@ -17,7 +17,9 @@
#include <cstring> // strlen
#include <cstdlib> // mbtowc
+#ifndef BOOST_NO_CWCHAR
#include <cwchar> // wcslen
+#endif
#include <boost/config.hpp>
#if defined(BOOST_NO_STDC_NAMESPACE)
diff --git a/boost/archive/iterators/base64_from_binary.hpp b/boost/archive/iterators/base64_from_binary.hpp
index 00c4e10c10..ee84994439 100644
--- a/boost/archive/iterators/base64_from_binary.hpp
+++ b/boost/archive/iterators/base64_from_binary.hpp
@@ -41,7 +41,7 @@ template<class CharType>
struct from_6_bit {
typedef CharType result_type;
CharType operator()(CharType t) const{
- const char * lookup_table =
+ static const char * lookup_table =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789"
diff --git a/boost/archive/iterators/binary_from_base64.hpp b/boost/archive/iterators/binary_from_base64.hpp
index 2eb7828251..89b8f889da 100644
--- a/boost/archive/iterators/binary_from_base64.hpp
+++ b/boost/archive/iterators/binary_from_base64.hpp
@@ -37,7 +37,7 @@ template<class CharType>
struct to_6_bit {
typedef CharType result_type;
CharType operator()(CharType t) const{
- const signed char lookup_table[] = {
+ static const signed char lookup_table[] = {
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,
diff --git a/boost/archive/iterators/escape.hpp b/boost/archive/iterators/escape.hpp
index a1fee91420..103b31e0fe 100644
--- a/boost/archive/iterators/escape.hpp
+++ b/boost/archive/iterators/escape.hpp
@@ -102,7 +102,8 @@ public:
super_t(base),
m_bnext(NULL),
m_bend(NULL),
- m_full(false)
+ m_full(false),
+ m_current_value(0)
{
}
};
diff --git a/boost/archive/iterators/istream_iterator.hpp b/boost/archive/iterators/istream_iterator.hpp
index 9a1d555c10..a187f605e6 100644
--- a/boost/archive/iterators/istream_iterator.hpp
+++ b/boost/archive/iterators/istream_iterator.hpp
@@ -56,7 +56,7 @@ class istream_iterator :
//Access the value referred to
Elem dereference() const {
- return m_istream->peek();
+ return static_cast<Elem>(m_istream->peek());
}
void increment(){
@@ -75,14 +75,14 @@ public:
}
istream_iterator() :
- m_istream(NULL)
+ m_istream(NULL),
+ m_current_value(NULL)
{}
istream_iterator(const istream_iterator<Elem> & rhs) :
m_istream(rhs.m_istream),
m_current_value(rhs.m_current_value)
{}
-
};
} // namespace iterators
diff --git a/boost/archive/iterators/mb_from_wchar.hpp b/boost/archive/iterators/mb_from_wchar.hpp
index b6dc9b2151..05df71c258 100644
--- a/boost/archive/iterators/mb_from_wchar.hpp
+++ b/boost/archive/iterators/mb_from_wchar.hpp
@@ -18,8 +18,9 @@
#include <boost/assert.hpp>
#include <cstddef> // size_t
+#ifndef BOOST_NO_CWCHAR
#include <cwchar> // mbstate_t
-
+#endif
#include <boost/config.hpp>
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std{
diff --git a/boost/archive/iterators/transform_width.hpp b/boost/archive/iterators/transform_width.hpp
index d042560e29..09c050a927 100644
--- a/boost/archive/iterators/transform_width.hpp
+++ b/boost/archive/iterators/transform_width.hpp
@@ -111,6 +111,7 @@ public:
transform_width(T start) :
super_t(Base(static_cast< T >(start))),
m_buffer_out_full(false),
+ m_buffer_out(0),
// To disable GCC warning, but not truly necessary
//(m_buffer_in will be initialized later before being
//used because m_remaining_bits == 0)
diff --git a/boost/archive/iterators/wchar_from_mb.hpp b/boost/archive/iterators/wchar_from_mb.hpp
index 52a44bdc79..2af8f6401f 100644
--- a/boost/archive/iterators/wchar_from_mb.hpp
+++ b/boost/archive/iterators/wchar_from_mb.hpp
@@ -19,7 +19,9 @@
#include <boost/assert.hpp>
#include <cctype>
#include <cstddef> // size_t
+#ifndef BOOST_NO_CWCHAR
#include <cwchar> // mbstate_t
+#endif
#include <algorithm> // copy
#include <boost/config.hpp>
diff --git a/boost/archive/wcslen.hpp b/boost/archive/wcslen.hpp
index 2a3d6351d4..0b60004f09 100644
--- a/boost/archive/wcslen.hpp
+++ b/boost/archive/wcslen.hpp
@@ -44,7 +44,9 @@ inline std::size_t wcslen(const wchar_t * ws)
#else
+#ifndef BOOST_NO_CWCHAR
#include <cwchar>
+#endif
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std{ using ::wcslen; }
#endif
diff --git a/boost/asio/detail/config.hpp b/boost/asio/detail/config.hpp
index baeb86d78e..afe400e5b7 100644
--- a/boost/asio/detail/config.hpp
+++ b/boost/asio/detail/config.hpp
@@ -65,7 +65,8 @@
#if !defined(BOOST_ASIO_MSVC)
# if defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_MSVC)
# define BOOST_ASIO_MSVC BOOST_MSVC
-# elif defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__EDG_VERSION__)
+# elif defined(_MSC_VER) && (defined(__INTELLISENSE__) \
+ || (!defined(__MWERKS__) && !defined(__EDG_VERSION__)))
# define BOOST_ASIO_MSVC _MSC_VER
# endif // defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_MSVC)
#endif // defined(BOOST_ASIO_MSVC)
@@ -154,6 +155,11 @@
# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4)
# endif // defined(__GNUC__)
+# if defined(BOOST_ASIO_MSVC)
+# if (_MSC_VER >= 1900)
+# define BOOST_ASIO_HAS_VARIADIC_TEMPLATES 1
+# endif // (_MSC_VER >= 1900)
+# endif // defined(BOOST_ASIO_MSVC)
# endif // !defined(BOOST_ASIO_DISABLE_VARIADIC_TEMPLATES)
#endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
@@ -172,6 +178,11 @@
# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)
# endif // defined(__GNUC__)
+# if defined(BOOST_ASIO_MSVC)
+# if (_MSC_VER >= 1900)
+# define BOOST_ASIO_HAS_CONSTEXPR 1
+# endif // (_MSC_VER >= 1900)
+# endif // defined(BOOST_ASIO_MSVC)
# endif // !defined(BOOST_ASIO_DISABLE_CONSTEXPR)
#endif // !defined(BOOST_ASIO_HAS_CONSTEXPR)
#if !defined(BOOST_ASIO_CONSTEXPR)
@@ -296,11 +307,11 @@
# endif // (__cplusplus >= 201103)
# endif // defined(__clang__)
# if defined(__GNUC__)
-# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)
# if defined(__GXX_EXPERIMENTAL_CXX0X__)
# define BOOST_ASIO_HAS_STD_ATOMIC 1
# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
-# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)
# endif // defined(__GNUC__)
# if defined(BOOST_ASIO_MSVC)
# if (_MSC_VER >= 1700)
@@ -988,12 +999,14 @@
# if defined(__linux__)
# if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
# if ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)
-# if !defined(__INTEL_COMPILER) && !defined(__ICL)
+# if !defined(__INTEL_COMPILER) && !defined(__ICL) \
+ && !(defined(__clang__) && defined(__ANDROID__))
# define BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION 1
# define BOOST_ASIO_THREAD_KEYWORD __thread
# elif defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100)
# define BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION 1
# endif // defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100)
+ // && !(defined(__clang__) && defined(__ANDROID__))
# endif // ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)
# endif // defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
# endif // defined(__linux__)
diff --git a/boost/asio/detail/dev_poll_reactor.hpp b/boost/asio/detail/dev_poll_reactor.hpp
index db6f3d1b8f..17f57d5221 100644
--- a/boost/asio/detail/dev_poll_reactor.hpp
+++ b/boost/asio/detail/dev_poll_reactor.hpp
@@ -102,15 +102,21 @@ public:
BOOST_ASIO_DECL void cancel_ops(socket_type descriptor, per_descriptor_data&);
// Cancel any operations that are running against the descriptor and remove
- // its registration from the reactor.
+ // its registration from the reactor. The reactor resources associated with
+ // the descriptor must be released by calling cleanup_descriptor_data.
BOOST_ASIO_DECL void deregister_descriptor(socket_type descriptor,
per_descriptor_data&, bool closing);
- // Cancel any operations that are running against the descriptor and remove
- // its registration from the reactor.
+ // Remove the descriptor's registration from the reactor. The reactor
+ // resources associated with the descriptor must be released by calling
+ // cleanup_descriptor_data.
BOOST_ASIO_DECL void deregister_internal_descriptor(
socket_type descriptor, per_descriptor_data&);
+ // Perform any post-deregistration cleanup tasks associated with the
+ // descriptor data.
+ BOOST_ASIO_DECL void cleanup_descriptor_data(per_descriptor_data&);
+
// Add a new timer queue to the reactor.
template <typename Time_Traits>
void add_timer_queue(timer_queue<Time_Traits>& queue);
diff --git a/boost/asio/detail/epoll_reactor.hpp b/boost/asio/detail/epoll_reactor.hpp
index 64c5b2704c..34ed0370f5 100644
--- a/boost/asio/detail/epoll_reactor.hpp
+++ b/boost/asio/detail/epoll_reactor.hpp
@@ -63,6 +63,7 @@ public:
BOOST_ASIO_DECL descriptor_state();
void set_ready_events(uint32_t events) { task_result_ = events; }
+ void add_ready_events(uint32_t events) { task_result_ |= events; }
BOOST_ASIO_DECL operation* perform_io(uint32_t events);
BOOST_ASIO_DECL static void do_complete(
io_service_impl* owner, operation* base,
@@ -123,14 +124,22 @@ public:
per_descriptor_data& descriptor_data);
// Cancel any operations that are running against the descriptor and remove
- // its registration from the reactor.
+ // its registration from the reactor. The reactor resources associated with
+ // the descriptor must be released by calling cleanup_descriptor_data.
BOOST_ASIO_DECL void deregister_descriptor(socket_type descriptor,
per_descriptor_data& descriptor_data, bool closing);
- // Remote the descriptor's registration from the reactor.
+ // Remove the descriptor's registration from the reactor. The reactor
+ // resources associated with the descriptor must be released by calling
+ // cleanup_descriptor_data.
BOOST_ASIO_DECL void deregister_internal_descriptor(
socket_type descriptor, per_descriptor_data& descriptor_data);
+ // Perform any post-deregistration cleanup tasks associated with the
+ // descriptor data.
+ BOOST_ASIO_DECL void cleanup_descriptor_data(
+ per_descriptor_data& descriptor_data);
+
// Add a new timer queue to the reactor.
template <typename Time_Traits>
void add_timer_queue(timer_queue<Time_Traits>& timer_queue);
diff --git a/boost/asio/detail/impl/dev_poll_reactor.ipp b/boost/asio/detail/impl/dev_poll_reactor.ipp
index efe2ba7086..7efb05ed02 100644
--- a/boost/asio/detail/impl/dev_poll_reactor.ipp
+++ b/boost/asio/detail/impl/dev_poll_reactor.ipp
@@ -235,6 +235,11 @@ void dev_poll_reactor::deregister_internal_descriptor(
op_queue_[i].cancel_operations(descriptor, ops, ec);
}
+void dev_poll_reactor::cleanup_descriptor_data(
+ dev_poll_reactor::per_descriptor_data&)
+{
+}
+
void dev_poll_reactor::run(bool block, op_queue<operation>& ops)
{
boost::asio::detail::mutex::scoped_lock lock(mutex_);
diff --git a/boost/asio/detail/impl/epoll_reactor.ipp b/boost/asio/detail/impl/epoll_reactor.ipp
index 610ce31ce5..3d3d244e0a 100644
--- a/boost/asio/detail/impl/epoll_reactor.ipp
+++ b/boost/asio/detail/impl/epoll_reactor.ipp
@@ -359,10 +359,16 @@ void epoll_reactor::deregister_descriptor(socket_type descriptor,
descriptor_lock.unlock();
- free_descriptor_state(descriptor_data);
- descriptor_data = 0;
-
io_service_.post_deferred_completions(ops);
+
+ // Leave descriptor_data set so that it will be freed by the subsequent
+ // call to cleanup_descriptor_data.
+ }
+ else
+ {
+ // We are shutting down, so prevent cleanup_descriptor_data from freeing
+ // the descriptor_data object and let the destructor free it instead.
+ descriptor_data = 0;
}
}
@@ -388,6 +394,22 @@ void epoll_reactor::deregister_internal_descriptor(socket_type descriptor,
descriptor_lock.unlock();
+ // Leave descriptor_data set so that it will be freed by the subsequent
+ // call to cleanup_descriptor_data.
+ }
+ else
+ {
+ // We are shutting down, so prevent cleanup_descriptor_data from freeing
+ // the descriptor_data object and let the destructor free it instead.
+ descriptor_data = 0;
+ }
+}
+
+void epoll_reactor::cleanup_descriptor_data(
+ per_descriptor_data& descriptor_data)
+{
+ if (descriptor_data)
+ {
free_descriptor_state(descriptor_data);
descriptor_data = 0;
}
@@ -451,8 +473,15 @@ void epoll_reactor::run(bool block, op_queue<operation>& ops)
// don't call work_started() here. This still allows the io_service to
// stop if the only remaining operations are descriptor operations.
descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr);
- descriptor_data->set_ready_events(events[i].events);
- ops.push(descriptor_data);
+ if (!ops.is_enqueued(descriptor_data))
+ {
+ descriptor_data->set_ready_events(events[i].events);
+ ops.push(descriptor_data);
+ }
+ else
+ {
+ descriptor_data->add_ready_events(events[i].events);
+ }
}
}
diff --git a/boost/asio/detail/impl/kqueue_reactor.ipp b/boost/asio/detail/impl/kqueue_reactor.ipp
index b4a7a10b71..8057606ce6 100644
--- a/boost/asio/detail/impl/kqueue_reactor.ipp
+++ b/boost/asio/detail/impl/kqueue_reactor.ipp
@@ -312,10 +312,16 @@ void kqueue_reactor::deregister_descriptor(socket_type descriptor,
descriptor_lock.unlock();
- free_descriptor_state(descriptor_data);
- descriptor_data = 0;
-
io_service_.post_deferred_completions(ops);
+
+ // Leave descriptor_data set so that it will be freed by the subsequent
+ // call to cleanup_descriptor_data.
+ }
+ else
+ {
+ // We are shutting down, so prevent cleanup_descriptor_data from freeing
+ // the descriptor_data object and let the destructor free it instead.
+ descriptor_data = 0;
}
}
@@ -345,6 +351,22 @@ void kqueue_reactor::deregister_internal_descriptor(socket_type descriptor,
descriptor_lock.unlock();
+ // Leave descriptor_data set so that it will be freed by the subsequent
+ // call to cleanup_descriptor_data.
+ }
+ else
+ {
+ // We are shutting down, so prevent cleanup_descriptor_data from freeing
+ // the descriptor_data object and let the destructor free it instead.
+ descriptor_data = 0;
+ }
+}
+
+void kqueue_reactor::cleanup_descriptor_data(
+ per_descriptor_data& descriptor_data)
+{
+ if (descriptor_data)
+ {
free_descriptor_state(descriptor_data);
descriptor_data = 0;
}
diff --git a/boost/asio/detail/impl/reactive_descriptor_service.ipp b/boost/asio/detail/impl/reactive_descriptor_service.ipp
index 56caec9fd3..a0300c47d0 100644
--- a/boost/asio/detail/impl/reactive_descriptor_service.ipp
+++ b/boost/asio/detail/impl/reactive_descriptor_service.ipp
@@ -88,10 +88,12 @@ void reactive_descriptor_service::destroy(
reactor_.deregister_descriptor(impl.descriptor_, impl.reactor_data_,
(impl.state_ & descriptor_ops::possible_dup) == 0);
- }
- boost::system::error_code ignored_ec;
- descriptor_ops::close(impl.descriptor_, impl.state_, ignored_ec);
+ boost::system::error_code ignored_ec;
+ descriptor_ops::close(impl.descriptor_, impl.state_, ignored_ec);
+
+ reactor_.cleanup_descriptor_data(impl.reactor_data_);
+ }
}
boost::system::error_code reactive_descriptor_service::assign(
@@ -128,9 +130,15 @@ boost::system::error_code reactive_descriptor_service::close(
reactor_.deregister_descriptor(impl.descriptor_, impl.reactor_data_,
(impl.state_ & descriptor_ops::possible_dup) == 0);
- }
- descriptor_ops::close(impl.descriptor_, impl.state_, ec);
+ descriptor_ops::close(impl.descriptor_, impl.state_, ec);
+
+ reactor_.cleanup_descriptor_data(impl.reactor_data_);
+ }
+ else
+ {
+ ec = boost::system::error_code();
+ }
// The descriptor is closed by the OS even if close() returns an error.
//
@@ -154,6 +162,7 @@ reactive_descriptor_service::release(
BOOST_ASIO_HANDLER_OPERATION(("descriptor", &impl, "release"));
reactor_.deregister_descriptor(impl.descriptor_, impl.reactor_data_, false);
+ reactor_.cleanup_descriptor_data(impl.reactor_data_);
construct(impl);
}
diff --git a/boost/asio/detail/impl/reactive_socket_service_base.ipp b/boost/asio/detail/impl/reactive_socket_service_base.ipp
index 21e77e9f93..3594ae0528 100644
--- a/boost/asio/detail/impl/reactive_socket_service_base.ipp
+++ b/boost/asio/detail/impl/reactive_socket_service_base.ipp
@@ -89,6 +89,8 @@ void reactive_socket_service_base::destroy(
boost::system::error_code ignored_ec;
socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);
+
+ reactor_.cleanup_descriptor_data(impl.reactor_data_);
}
}
@@ -102,9 +104,15 @@ boost::system::error_code reactive_socket_service_base::close(
reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,
(impl.state_ & socket_ops::possible_dup) == 0);
- }
- socket_ops::close(impl.socket_, impl.state_, false, ec);
+ socket_ops::close(impl.socket_, impl.state_, false, ec);
+
+ reactor_.cleanup_descriptor_data(impl.reactor_data_);
+ }
+ else
+ {
+ ec = boost::system::error_code();
+ }
// The descriptor is closed by the OS even if close() returns an error.
//
@@ -224,7 +232,7 @@ void reactive_socket_service_base::start_accept_op(
reactor_op* op, bool is_continuation, bool peer_is_open)
{
if (!peer_is_open)
- start_op(impl, reactor::read_op, op, true, is_continuation, false);
+ start_op(impl, reactor::read_op, op, is_continuation, true, false);
else
{
op->ec_ = boost::asio::error::already_open;
diff --git a/boost/asio/detail/impl/select_reactor.ipp b/boost/asio/detail/impl/select_reactor.ipp
index 80686eaf97..869f73492b 100644
--- a/boost/asio/detail/impl/select_reactor.ipp
+++ b/boost/asio/detail/impl/select_reactor.ipp
@@ -163,6 +163,11 @@ void select_reactor::deregister_internal_descriptor(
op_queue_[i].cancel_operations(descriptor, ops);
}
+void select_reactor::cleanup_descriptor_data(
+ select_reactor::per_descriptor_data&)
+{
+}
+
void select_reactor::run(bool block, op_queue<operation>& ops)
{
boost::asio::detail::mutex::scoped_lock lock(mutex_);
diff --git a/boost/asio/detail/impl/signal_set_service.ipp b/boost/asio/detail/impl/signal_set_service.ipp
index 56313e0923..95ea8bee21 100644
--- a/boost/asio/detail/impl/signal_set_service.ipp
+++ b/boost/asio/detail/impl/signal_set_service.ipp
@@ -187,6 +187,7 @@ void signal_set_service::fork_service(
state->fork_prepared_ = true;
lock.unlock();
reactor_.deregister_internal_descriptor(read_descriptor, reactor_data_);
+ reactor_.cleanup_descriptor_data(reactor_data_);
}
break;
case boost::asio::io_service::fork_parent:
@@ -539,8 +540,9 @@ void signal_set_service::remove_service(signal_set_service* service)
// Disable the pipe readiness notifications.
int read_descriptor = state->read_descriptor_;
lock.unlock();
- service->reactor_.deregister_descriptor(
- read_descriptor, service->reactor_data_, false);
+ service->reactor_.deregister_internal_descriptor(
+ read_descriptor, service->reactor_data_);
+ service->reactor_.cleanup_descriptor_data(service->reactor_data_);
lock.lock();
#endif // !defined(BOOST_ASIO_WINDOWS)
// && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
diff --git a/boost/asio/detail/impl/win_iocp_socket_service_base.ipp b/boost/asio/detail/impl/win_iocp_socket_service_base.ipp
index 22818f7e92..93f5ed0713 100644
--- a/boost/asio/detail/impl/win_iocp_socket_service_base.ipp
+++ b/boost/asio/detail/impl/win_iocp_socket_service_base.ipp
@@ -177,9 +177,16 @@ boost::system::error_code win_iocp_socket_service_base::close(
reinterpret_cast<void**>(&reactor_), 0, 0));
if (r)
r->deregister_descriptor(impl.socket_, impl.reactor_data_, true);
- }
- socket_ops::close(impl.socket_, impl.state_, false, ec);
+ socket_ops::close(impl.socket_, impl.state_, false, ec);
+
+ if (r)
+ r->cleanup_descriptor_data(impl.reactor_data_);
+ }
+ else
+ {
+ ec = boost::system::error_code();
+ }
impl.socket_ = invalid_socket;
impl.state_ = 0;
@@ -629,10 +636,14 @@ void win_iocp_socket_service_base::close_for_destruction(
reinterpret_cast<void**>(&reactor_), 0, 0));
if (r)
r->deregister_descriptor(impl.socket_, impl.reactor_data_, true);
+
+ boost::system::error_code ignored_ec;
+ socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);
+
+ if (r)
+ r->cleanup_descriptor_data(impl.reactor_data_);
}
- boost::system::error_code ignored_ec;
- socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);
impl.socket_ = invalid_socket;
impl.state_ = 0;
impl.cancel_token_.reset();
diff --git a/boost/asio/detail/kqueue_reactor.hpp b/boost/asio/detail/kqueue_reactor.hpp
index 6aba2b264f..c6182b4d55 100644
--- a/boost/asio/detail/kqueue_reactor.hpp
+++ b/boost/asio/detail/kqueue_reactor.hpp
@@ -125,14 +125,22 @@ public:
per_descriptor_data& descriptor_data);
// Cancel any operations that are running against the descriptor and remove
- // its registration from the reactor.
+ // its registration from the reactor. The reactor resources associated with
+ // the descriptor must be released by calling cleanup_descriptor_data.
BOOST_ASIO_DECL void deregister_descriptor(socket_type descriptor,
per_descriptor_data& descriptor_data, bool closing);
- // Remote the descriptor's registration from the reactor.
+ // Remove the descriptor's registration from the reactor. The reactor
+ // resources associated with the descriptor must be released by calling
+ // cleanup_descriptor_data.
BOOST_ASIO_DECL void deregister_internal_descriptor(
socket_type descriptor, per_descriptor_data& descriptor_data);
+ // Perform any post-deregistration cleanup tasks associated with the
+ // descriptor data.
+ BOOST_ASIO_DECL void cleanup_descriptor_data(
+ per_descriptor_data& descriptor_data);
+
// Add a new timer queue to the reactor.
template <typename Time_Traits>
void add_timer_queue(timer_queue<Time_Traits>& queue);
diff --git a/boost/asio/detail/op_queue.hpp b/boost/asio/detail/op_queue.hpp
index 9605248567..89f318eedf 100644
--- a/boost/asio/detail/op_queue.hpp
+++ b/boost/asio/detail/op_queue.hpp
@@ -139,6 +139,12 @@ public:
return front_ == 0;
}
+ // Test whether an operation is already enqueued.
+ bool is_enqueued(Operation* o) const
+ {
+ return op_queue_access::next(o) != 0 || back_ == o;
+ }
+
private:
friend class op_queue_access;
diff --git a/boost/asio/detail/select_reactor.hpp b/boost/asio/detail/select_reactor.hpp
index 69b04c82b5..d6f75242e5 100644
--- a/boost/asio/detail/select_reactor.hpp
+++ b/boost/asio/detail/select_reactor.hpp
@@ -107,13 +107,20 @@ public:
BOOST_ASIO_DECL void cancel_ops(socket_type descriptor, per_descriptor_data&);
// Cancel any operations that are running against the descriptor and remove
- // its registration from the reactor.
+ // its registration from the reactor. The reactor resources associated with
+ // the descriptor must be released by calling cleanup_descriptor_data.
BOOST_ASIO_DECL void deregister_descriptor(socket_type descriptor,
per_descriptor_data&, bool closing);
- // Remote the descriptor's registration from the reactor.
+ // Remove the descriptor's registration from the reactor. The reactor
+ // resources associated with the descriptor must be released by calling
+ // cleanup_descriptor_data.
BOOST_ASIO_DECL void deregister_internal_descriptor(
- socket_type descriptor, per_descriptor_data& descriptor_data);
+ socket_type descriptor, per_descriptor_data&);
+
+ // Perform any post-deregistration cleanup tasks associated with the
+ // descriptor data.
+ BOOST_ASIO_DECL void cleanup_descriptor_data(per_descriptor_data&);
// Move descriptor registration from one descriptor_data object to another.
BOOST_ASIO_DECL void move_descriptor(socket_type descriptor,
diff --git a/boost/asio/detail/socket_types.hpp b/boost/asio/detail/socket_types.hpp
index 8467118b54..0768f70077 100644
--- a/boost/asio/detail/socket_types.hpp
+++ b/boost/asio/detail/socket_types.hpp
@@ -57,7 +57,11 @@
# include <boost/asio/detail/old_win_sdk_compat.hpp>
#else
# include <sys/ioctl.h>
-# if !defined(__SYMBIAN32__)
+# if (defined(__MACH__) && defined(__APPLE__)) \
+ || defined(__FreeBSD__) || defined(__NetBSD__) \
+ || defined(__OpenBSD__) || defined(__linux__)
+# include <poll.h>
+# elif !defined(__SYMBIAN32__)
# include <sys/poll.h>
# endif
# include <sys/types.h>
diff --git a/boost/asio/detail/winapi_thread.hpp b/boost/asio/detail/winapi_thread.hpp
index 204e73f42a..79aba9b519 100644
--- a/boost/asio/detail/winapi_thread.hpp
+++ b/boost/asio/detail/winapi_thread.hpp
@@ -20,8 +20,8 @@
#if defined(BOOST_ASIO_WINDOWS)
#if defined(BOOST_ASIO_WINDOWS_APP) || defined(UNDER_CE)
-#include <memory>
#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/scoped_ptr.hpp>
#include <boost/asio/detail/socket_types.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/error.hpp>
@@ -42,7 +42,7 @@ public:
template <typename Function>
winapi_thread(Function f, unsigned int = 0)
{
- std::auto_ptr<func_base> arg(new func<Function>(f));
+ scoped_ptr<func_base> arg(new func<Function>(f));
DWORD thread_id = 0;
thread_ = ::CreateThread(0, 0, winapi_thread_function,
arg.get(), 0, &thread_id);
@@ -106,7 +106,7 @@ private:
inline DWORD WINAPI winapi_thread_function(LPVOID arg)
{
- std::auto_ptr<winapi_thread::func_base> func(
+ scoped_ptr<winapi_thread::func_base> func(
static_cast<winapi_thread::func_base*>(arg));
func->run();
return 0;
diff --git a/boost/asio/use_future.hpp b/boost/asio/use_future.hpp
index 43f6102e4d..e4ce7f7975 100644
--- a/boost/asio/use_future.hpp
+++ b/boost/asio/use_future.hpp
@@ -78,10 +78,10 @@ private:
/**
* See the documentation for boost::asio::use_future_t for a usage example.
*/
-#if defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
-constexpr use_future_t<> use_future;
-#elif defined(BOOST_ASIO_MSVC)
+#if defined(BOOST_ASIO_MSVC)
__declspec(selectany) use_future_t<> use_future;
+#elif defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
+constexpr use_future_t<> use_future;
#endif
} // namespace asio
diff --git a/boost/asio/version.hpp b/boost/asio/version.hpp
index 7dfc1c3d18..76b6440b01 100644
--- a/boost/asio/version.hpp
+++ b/boost/asio/version.hpp
@@ -18,6 +18,6 @@
// BOOST_ASIO_VERSION % 100 is the sub-minor version
// BOOST_ASIO_VERSION / 100 % 1000 is the minor version
// BOOST_ASIO_VERSION / 100000 is the major version
-#define BOOST_ASIO_VERSION 101009 // 1.10.9
+#define BOOST_ASIO_VERSION 101010 // 1.10.10
#endif // BOOST_ASIO_VERSION_HPP
diff --git a/boost/atomic/detail/atomic_template.hpp b/boost/atomic/detail/atomic_template.hpp
index dd3c741506..7bbc1fffad 100644
--- a/boost/atomic/detail/atomic_template.hpp
+++ b/boost/atomic/detail/atomic_template.hpp
@@ -19,11 +19,13 @@
#include <cstddef>
#include <boost/cstdint.hpp>
#include <boost/assert.hpp>
-#include <boost/type_traits/is_signed.hpp>
-#include <boost/type_traits/is_integral.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/bitwise_cast.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
+#include <boost/atomic/detail/type_traits/is_signed.hpp>
+#include <boost/atomic/detail/type_traits/is_integral.hpp>
+#include <boost/atomic/detail/type_traits/is_function.hpp>
+#include <boost/atomic/detail/type_traits/conditional.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -56,7 +58,19 @@ BOOST_FORCEINLINE BOOST_CONSTEXPR bool cas_failure_order_must_not_be_stronger_th
return (failure_order & 15u) <= (success_order & 15u);
}
-template< typename T, bool IsInt = boost::is_integral< T >::value >
+template< typename T, bool IsFunction = boost::atomics::detail::is_function< T >::value >
+struct classify_pointer
+{
+ typedef void* type;
+};
+
+template< typename T >
+struct classify_pointer< T, true >
+{
+ typedef void type;
+};
+
+template< typename T, bool IsInt = boost::atomics::detail::is_integral< T >::value >
struct classify
{
typedef void type;
@@ -66,21 +80,157 @@ template< typename T >
struct classify< T, true > { typedef int type; };
template< typename T >
-struct classify< T*, false > { typedef void* type; };
+struct classify< T*, false > { typedef typename classify_pointer< T >::type type; };
+
+template< >
+struct classify< void*, false > { typedef void type; };
+
+template< >
+struct classify< const void*, false > { typedef void type; };
+
+template< >
+struct classify< volatile void*, false > { typedef void type; };
+
+template< >
+struct classify< const volatile void*, false > { typedef void type; };
+
+template< typename T, typename U >
+struct classify< T U::*, false > { typedef void type; };
+
+template< bool >
+struct boolean_constant {};
+typedef boolean_constant< true > true_constant;
+typedef boolean_constant< false > false_constant;
+
template< typename T, typename Kind >
class base_atomic;
+//! General template. Implementation for user-defined types, such as structs and enums, and pointers to non-object types
+template< typename T >
+class base_atomic< T, void >
+{
+public:
+ typedef T value_type;
+
+protected:
+ typedef atomics::detail::operations< storage_size_of< value_type >::value, false > operations;
+ typedef typename boost::atomics::detail::conditional< sizeof(value_type) <= sizeof(void*), value_type, value_type const& >::type value_arg_type;
+
+public:
+ typedef typename operations::storage_type storage_type;
+
+private:
+ typedef boolean_constant< sizeof(value_type) == sizeof(storage_type) > value_matches_storage;
+
+protected:
+ typename operations::aligned_storage_type m_storage;
+
+public:
+ BOOST_FORCEINLINE explicit base_atomic(value_arg_type v = value_type()) BOOST_NOEXCEPT : m_storage(atomics::detail::bitwise_cast< storage_type >(v))
+ {
+ }
+
+ BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT(order != memory_order_consume);
+ BOOST_ASSERT(order != memory_order_acquire);
+ BOOST_ASSERT(order != memory_order_acq_rel);
+
+ operations::store(m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order);
+ }
+
+ BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT(order != memory_order_release);
+ BOOST_ASSERT(order != memory_order_acq_rel);
+
+ return atomics::detail::bitwise_cast< value_type >(operations::load(m_storage.value, order));
+ }
+
+ BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
+ {
+ return atomics::detail::bitwise_cast< value_type >(operations::exchange(m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order));
+ }
+
+ BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT(failure_order != memory_order_release);
+ BOOST_ASSERT(failure_order != memory_order_acq_rel);
+ BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
+
+ return compare_exchange_strong_impl(expected, desired, success_order, failure_order, value_matches_storage());
+ }
+
+ BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
+ {
+ return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
+ }
+
+ BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT(failure_order != memory_order_release);
+ BOOST_ASSERT(failure_order != memory_order_acq_rel);
+ BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
+
+ return compare_exchange_weak_impl(expected, desired, success_order, failure_order, value_matches_storage());
+ }
+
+ BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
+ {
+ return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
+ }
+
+ BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
+ BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
+
+private:
+ BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, true_constant) volatile BOOST_NOEXCEPT
+ {
+#if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
+ return operations::compare_exchange_strong(m_storage.value, reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
+#else
+ return compare_exchange_strong_impl(expected, desired, success_order, failure_order, false_constant());
+#endif
+ }
+
+ BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, false_constant) volatile BOOST_NOEXCEPT
+ {
+ storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected);
+ const bool res = operations::compare_exchange_strong(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
+ expected = atomics::detail::bitwise_cast< value_type >(old_value);
+ return res;
+ }
+
+ BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, true_constant) volatile BOOST_NOEXCEPT
+ {
+#if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
+ return operations::compare_exchange_weak(m_storage.value, reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
+#else
+ return compare_exchange_weak_impl(expected, desired, success_order, failure_order, false_constant());
+#endif
+ }
+
+ BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, false_constant) volatile BOOST_NOEXCEPT
+ {
+ storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected);
+ const bool res = operations::compare_exchange_weak(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
+ expected = atomics::detail::bitwise_cast< value_type >(old_value);
+ return res;
+ }
+};
+
+
//! Implementation for integers
template< typename T >
class base_atomic< T, int >
{
-private:
+public:
typedef T value_type;
typedef T difference_type;
protected:
- typedef atomics::detail::operations< storage_size_of< value_type >::value, boost::is_signed< T >::value > operations;
+ typedef atomics::detail::operations< storage_size_of< value_type >::value, boost::atomics::detail::is_signed< T >::value > operations;
typedef value_type value_arg_type;
public:
@@ -131,10 +281,14 @@ public:
BOOST_ASSERT(failure_order != memory_order_acq_rel);
BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
+#if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
+ return operations::compare_exchange_strong(m_storage.value, reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order);
+#else
storage_type old_value = static_cast< storage_type >(expected);
const bool res = operations::compare_exchange_strong(m_storage.value, old_value, static_cast< storage_type >(desired), success_order, failure_order);
expected = static_cast< value_type >(old_value);
return res;
+#endif
}
BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
@@ -148,10 +302,14 @@ public:
BOOST_ASSERT(failure_order != memory_order_acq_rel);
BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
+#if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
+ return operations::compare_exchange_weak(m_storage.value, reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order);
+#else
storage_type old_value = static_cast< storage_type >(expected);
const bool res = operations::compare_exchange_weak(m_storage.value, old_value, static_cast< storage_type >(desired), success_order, failure_order);
expected = static_cast< value_type >(old_value);
return res;
+#endif
}
BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
@@ -174,11 +332,6 @@ public:
return static_cast< value_type >(operations::fetch_xor(m_storage.value, static_cast< storage_type >(v), order));
}
- BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT
- {
- return operations::is_lock_free(m_storage.value);
- }
-
BOOST_FORCEINLINE value_type operator++(int) volatile BOOST_NOEXCEPT
{
return fetch_add(1);
@@ -232,7 +385,7 @@ public:
template< >
class base_atomic< bool, int >
{
-private:
+public:
typedef bool value_type;
protected:
@@ -277,10 +430,14 @@ public:
BOOST_ASSERT(failure_order != memory_order_acq_rel);
BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
+#if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
+ return operations::compare_exchange_strong(m_storage.value, reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order);
+#else
storage_type old_value = static_cast< storage_type >(expected);
const bool res = operations::compare_exchange_strong(m_storage.value, old_value, static_cast< storage_type >(desired), success_order, failure_order);
expected = !!old_value;
return res;
+#endif
}
BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
@@ -294,10 +451,14 @@ public:
BOOST_ASSERT(failure_order != memory_order_acq_rel);
BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
+#if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
+ return operations::compare_exchange_weak(m_storage.value, reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order);
+#else
storage_type old_value = static_cast< storage_type >(expected);
const bool res = operations::compare_exchange_weak(m_storage.value, old_value, static_cast< storage_type >(desired), success_order, failure_order);
expected = !!old_value;
return res;
+#endif
}
BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
@@ -305,109 +466,16 @@ public:
return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
}
- BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT
- {
- return operations::is_lock_free(m_storage.value);
- }
-
- BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
- BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
-};
-
-
-//! Implementation for user-defined types, such as structs and enums
-template< typename T >
-class base_atomic< T, void >
-{
-private:
- typedef T value_type;
-
-protected:
- typedef atomics::detail::operations< storage_size_of< value_type >::value, false > operations;
- typedef value_type const& value_arg_type;
-
-public:
- typedef typename operations::storage_type storage_type;
-
-protected:
- typename operations::aligned_storage_type m_storage;
-
-public:
- BOOST_FORCEINLINE explicit base_atomic(value_type const& v = value_type()) BOOST_NOEXCEPT : m_storage(atomics::detail::bitwise_cast< storage_type >(v))
- {
- }
-
- BOOST_FORCEINLINE void store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
- {
- BOOST_ASSERT(order != memory_order_consume);
- BOOST_ASSERT(order != memory_order_acquire);
- BOOST_ASSERT(order != memory_order_acq_rel);
-
- operations::store(m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order);
- }
-
- BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
- {
- BOOST_ASSERT(order != memory_order_release);
- BOOST_ASSERT(order != memory_order_acq_rel);
-
- return atomics::detail::bitwise_cast< value_type >(operations::load(m_storage.value, order));
- }
-
- BOOST_FORCEINLINE value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
- {
- return atomics::detail::bitwise_cast< value_type >(operations::exchange(m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order));
- }
-
- BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
- {
- BOOST_ASSERT(failure_order != memory_order_release);
- BOOST_ASSERT(failure_order != memory_order_acq_rel);
- BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
-
- storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected);
- const bool res = operations::compare_exchange_strong(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
- expected = atomics::detail::bitwise_cast< value_type >(old_value);
- return res;
- }
-
- BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
- {
- return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
- }
-
- BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
- {
- BOOST_ASSERT(failure_order != memory_order_release);
- BOOST_ASSERT(failure_order != memory_order_acq_rel);
- BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
-
- storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected);
- const bool res = operations::compare_exchange_weak(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
- expected = atomics::detail::bitwise_cast< value_type >(old_value);
- return res;
- }
-
- BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
- {
- return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
- }
-
- BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT
- {
- return operations::is_lock_free(m_storage.value);
- }
-
BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
};
-//! Implementation for pointers
+//! Implementation for pointers to object types
template< typename T >
class base_atomic< T*, void* >
{
-private:
+public:
typedef T* value_type;
typedef std::ptrdiff_t difference_type;
@@ -465,10 +533,14 @@ public:
BOOST_ASSERT(failure_order != memory_order_acq_rel);
BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
+#if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
+ return operations::compare_exchange_strong(m_storage.value, reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
+#else
storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected);
const bool res = operations::compare_exchange_strong(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
expected = atomics::detail::bitwise_cast< value_type >(old_value);
return res;
+#endif
}
BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
@@ -482,10 +554,14 @@ public:
BOOST_ASSERT(failure_order != memory_order_acq_rel);
BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
+#if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
+ return operations::compare_exchange_weak(m_storage.value, reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
+#else
storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected);
const bool res = operations::compare_exchange_weak(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
expected = atomics::detail::bitwise_cast< value_type >(old_value);
return res;
+#endif
}
BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
@@ -493,11 +569,6 @@ public:
return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
}
- BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT
- {
- return operations::is_lock_free(m_storage.value);
- }
-
BOOST_FORCEINLINE value_type operator++(int) volatile BOOST_NOEXCEPT
{
return fetch_add(1);
@@ -532,136 +603,6 @@ public:
BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
};
-
-//! Implementation for void pointers
-template< >
-class base_atomic< void*, void* >
-{
-private:
- typedef void* value_type;
- typedef std::ptrdiff_t difference_type;
-
-protected:
- typedef atomics::detail::operations< storage_size_of< value_type >::value, false > operations;
- typedef value_type value_arg_type;
-
-public:
- typedef operations::storage_type storage_type;
-
-protected:
- operations::aligned_storage_type m_storage;
-
-public:
- BOOST_DEFAULTED_FUNCTION(base_atomic(), {})
- BOOST_FORCEINLINE explicit base_atomic(value_type const& v) BOOST_NOEXCEPT : m_storage(atomics::detail::bitwise_cast< storage_type >(v))
- {
- }
-
- BOOST_FORCEINLINE void store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
- {
- BOOST_ASSERT(order != memory_order_consume);
- BOOST_ASSERT(order != memory_order_acquire);
- BOOST_ASSERT(order != memory_order_acq_rel);
-
- operations::store(m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order);
- }
-
- BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
- {
- BOOST_ASSERT(order != memory_order_release);
- BOOST_ASSERT(order != memory_order_acq_rel);
-
- return atomics::detail::bitwise_cast< value_type >(operations::load(m_storage.value, order));
- }
-
- BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
- {
- return atomics::detail::bitwise_cast< value_type >(operations::fetch_add(m_storage.value, static_cast< storage_type >(v), order));
- }
-
- BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
- {
- return atomics::detail::bitwise_cast< value_type >(operations::fetch_sub(m_storage.value, static_cast< storage_type >(v), order));
- }
-
- BOOST_FORCEINLINE value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
- {
- return atomics::detail::bitwise_cast< value_type >(operations::exchange(m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order));
- }
-
- BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
- {
- BOOST_ASSERT(failure_order != memory_order_release);
- BOOST_ASSERT(failure_order != memory_order_acq_rel);
- BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
-
- storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected);
- const bool res = operations::compare_exchange_strong(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
- expected = atomics::detail::bitwise_cast< value_type >(old_value);
- return res;
- }
-
- BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
- {
- return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
- }
-
- BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
- {
- BOOST_ASSERT(failure_order != memory_order_release);
- BOOST_ASSERT(failure_order != memory_order_acq_rel);
- BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
-
- storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected);
- const bool res = operations::compare_exchange_weak(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
- expected = atomics::detail::bitwise_cast< value_type >(old_value);
- return res;
- }
-
- BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
- {
- return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
- }
-
- BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT
- {
- return operations::is_lock_free(m_storage.value);
- }
-
- BOOST_FORCEINLINE value_type operator++(int) volatile BOOST_NOEXCEPT
- {
- return fetch_add(1);
- }
-
- BOOST_FORCEINLINE value_type operator++() volatile BOOST_NOEXCEPT
- {
- return (char*)fetch_add(1) + 1;
- }
-
- BOOST_FORCEINLINE value_type operator--(int) volatile BOOST_NOEXCEPT
- {
- return fetch_sub(1);
- }
-
- BOOST_FORCEINLINE value_type operator--() volatile BOOST_NOEXCEPT
- {
- return (char*)fetch_sub(1) - 1;
- }
-
- BOOST_FORCEINLINE value_type operator+=(difference_type v) volatile BOOST_NOEXCEPT
- {
- return (char*)fetch_add(v) + v;
- }
-
- BOOST_FORCEINLINE value_type operator-=(difference_type v) volatile BOOST_NOEXCEPT
- {
- return (char*)fetch_sub(v) - v;
- }
-
- BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
- BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
-};
-
} // namespace detail
template< typename T >
@@ -669,11 +610,11 @@ class atomic :
public atomics::detail::base_atomic< T, typename atomics::detail::classify< T >::type >
{
private:
- typedef T value_type;
typedef atomics::detail::base_atomic< T, typename atomics::detail::classify< T >::type > base_type;
typedef typename base_type::value_arg_type value_arg_type;
public:
+ typedef typename base_type::value_type value_type;
typedef typename base_type::storage_type storage_type;
public:
@@ -694,11 +635,17 @@ public:
return v;
}
- BOOST_FORCEINLINE operator value_type() volatile const BOOST_NOEXCEPT
+ BOOST_FORCEINLINE operator value_type() const volatile BOOST_NOEXCEPT
{
return this->load();
}
+ BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT
+ {
+ // C++17 requires all instances of atomic<> return a value consistent with is_always_lock_free here
+ return is_always_lock_free;
+ }
+
BOOST_FORCEINLINE storage_type& storage() BOOST_NOEXCEPT { return this->m_storage.value; }
BOOST_FORCEINLINE storage_type volatile& storage() volatile BOOST_NOEXCEPT { return this->m_storage.value; }
BOOST_FORCEINLINE storage_type const& storage() const BOOST_NOEXCEPT { return this->m_storage.value; }
diff --git a/boost/atomic/detail/bitwise_cast.hpp b/boost/atomic/detail/bitwise_cast.hpp
index 1405a25d6a..4a285ecab2 100644
--- a/boost/atomic/detail/bitwise_cast.hpp
+++ b/boost/atomic/detail/bitwise_cast.hpp
@@ -25,6 +25,12 @@
#pragma once
#endif
+#if defined(BOOST_GCC) && (BOOST_GCC+0) >= 40600
+#pragma GCC diagnostic push
+// missing initializer for member var
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+#endif
+
namespace boost {
namespace atomics {
namespace detail {
@@ -34,7 +40,7 @@ BOOST_FORCEINLINE T* addressof(T& value) BOOST_NOEXCEPT
{
// Note: The point of using a local struct as the intermediate type instead of char is to avoid gcc warnings
// if T is a const volatile char*:
- // warning: casting ‘const volatile char* const’ to ‘const volatile char&’ does not dereference pointer
+ // warning: casting 'const volatile char* const' to 'const volatile char&' does not dereference pointer
// The local struct makes sure T is not related to the cast target type.
struct opaque_type;
return reinterpret_cast< T* >(&const_cast< opaque_type& >(reinterpret_cast< const volatile opaque_type& >(value)));
@@ -61,4 +67,8 @@ BOOST_FORCEINLINE To bitwise_cast(From const& from) BOOST_NOEXCEPT
} // namespace atomics
} // namespace boost
+#if defined(BOOST_GCC) && (BOOST_GCC+0) >= 40600
+#pragma GCC diagnostic pop
+#endif
+
#endif // BOOST_ATOMIC_DETAIL_BITWISE_CAST_HPP_INCLUDED_
diff --git a/boost/atomic/detail/config.hpp b/boost/atomic/detail/config.hpp
index 00f7bff696..7a43e23cbc 100644
--- a/boost/atomic/detail/config.hpp
+++ b/boost/atomic/detail/config.hpp
@@ -73,4 +73,30 @@
#define BOOST_ATOMIC_DETAIL_NO_ASM_RAX_RDX_PAIRS
#endif
+#if defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
+#if !(defined(BOOST_LIBSTDCXX11) && (BOOST_LIBSTDCXX_VERSION+0) >= 40700) /* libstdc++ from gcc >= 4.7 in C++11 mode */
+// This macro indicates that there is no <type_traits> standard header that is sufficient for Boost.Atomic needs.
+#define BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS
+#endif
+#endif // defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
+
+// Enable pointer/reference casts between storage and value when possible.
+// Note: Despite that MSVC does not employ strict aliasing rules for optimizations
+// and does not require an explicit markup for types that may alias, we still don't
+// enable the optimization for this compiler because at least MSVC-8 and 9 are known
+// to generate broken code sometimes when casts are used.
+#if defined(__GNUC__) && (!defined(BOOST_INTEL_CXX_VERSION) || (BOOST_INTEL_CXX_VERSION+0) >= 1300)
+#define BOOST_ATOMIC_DETAIL_MAY_ALIAS __attribute__((__may_alias__))
+#define BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS
+#elif defined(__has_attribute)
+#if __has_attribute(__may_alias__)
+#define BOOST_ATOMIC_DETAIL_MAY_ALIAS __attribute__((__may_alias__))
+#define BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS
+#endif
+#endif
+
+#if !defined(BOOST_ATOMIC_DETAIL_MAY_ALIAS)
+#define BOOST_ATOMIC_DETAIL_MAY_ALIAS
+#endif
+
#endif // BOOST_ATOMIC_DETAIL_CONFIG_HPP_INCLUDED_
diff --git a/boost/atomic/detail/ops_emulated.hpp b/boost/atomic/detail/ops_emulated.hpp
index a21128ec69..e15f37a680 100644
--- a/boost/atomic/detail/ops_emulated.hpp
+++ b/boost/atomic/detail/ops_emulated.hpp
@@ -142,11 +142,6 @@ struct emulated_operations
{
store(storage, (storage_type)0, order);
}
-
- static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
- {
- return false;
- }
};
template< std::size_t Size, bool Signed >
diff --git a/boost/atomic/detail/ops_gcc_alpha.hpp b/boost/atomic/detail/ops_gcc_alpha.hpp
index 15118f58a2..5a9deb42ea 100644
--- a/boost/atomic/detail/ops_gcc_alpha.hpp
+++ b/boost/atomic/detail/ops_gcc_alpha.hpp
@@ -339,11 +339,6 @@ struct operations< 4u, Signed > :
{
store(storage, 0, order);
}
-
- static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
- {
- return true;
- }
};
@@ -851,11 +846,6 @@ struct operations< 8u, Signed > :
{
store(storage, 0, order);
}
-
- static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
- {
- return true;
- }
};
diff --git a/boost/atomic/detail/ops_gcc_arm.hpp b/boost/atomic/detail/ops_gcc_arm.hpp
index e181b16853..86a75f5b25 100644
--- a/boost/atomic/detail/ops_gcc_arm.hpp
+++ b/boost/atomic/detail/ops_gcc_arm.hpp
@@ -404,11 +404,6 @@ struct operations< 4u, Signed > :
{
store(storage, 0, order);
}
-
- static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
- {
- return true;
- }
};
@@ -946,11 +941,6 @@ struct operations< 8u, Signed > :
{
store(storage, 0, order);
}
-
- static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
- {
- return true;
- }
};
#endif // defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXD_STREXD)
diff --git a/boost/atomic/detail/ops_gcc_atomic.hpp b/boost/atomic/detail/ops_gcc_atomic.hpp
index 0a34c01f16..4e1adae86a 100644
--- a/boost/atomic/detail/ops_gcc_atomic.hpp
+++ b/boost/atomic/detail/ops_gcc_atomic.hpp
@@ -161,11 +161,6 @@ struct gcc_atomic_operations
{
__atomic_clear(const_cast< storage_type* >(&storage), atomics::detail::convert_memory_order_to_gcc(order));
}
-
- static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile& storage) BOOST_NOEXCEPT
- {
- return __atomic_is_lock_free(sizeof(storage_type), &storage);
- }
};
#if BOOST_ATOMIC_INT128_LOCK_FREE > 0
diff --git a/boost/atomic/detail/ops_gcc_ppc.hpp b/boost/atomic/detail/ops_gcc_ppc.hpp
index 4183bc0485..76eae4e232 100644
--- a/boost/atomic/detail/ops_gcc_ppc.hpp
+++ b/boost/atomic/detail/ops_gcc_ppc.hpp
@@ -331,11 +331,6 @@ struct operations< 4u, Signed > :
{
store(storage, 0, order);
}
-
- static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
- {
- return true;
- }
};
@@ -758,11 +753,6 @@ struct operations< 8u, Signed > :
{
store(storage, 0, order);
}
-
- static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
- {
- return true;
- }
};
#endif // defined(__powerpc64__) || defined(__PPC64__)
diff --git a/boost/atomic/detail/ops_gcc_sparc.hpp b/boost/atomic/detail/ops_gcc_sparc.hpp
index fd42fa8095..08492ac69a 100644
--- a/boost/atomic/detail/ops_gcc_sparc.hpp
+++ b/boost/atomic/detail/ops_gcc_sparc.hpp
@@ -120,11 +120,6 @@ struct gcc_sparc_cas32 :
fence_after(order);
return v;
}
-
- static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
- {
- return true;
- }
};
template< bool Signed >
@@ -192,11 +187,6 @@ struct gcc_sparc_cas64 :
{
return compare_exchange_strong(storage, expected, desired, success_order, failure_order);
}
-
- static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
- {
- return true;
- }
};
template< bool Signed >
diff --git a/boost/atomic/detail/ops_gcc_sync.hpp b/boost/atomic/detail/ops_gcc_sync.hpp
index 2f41aff279..a9a9ae2f72 100644
--- a/boost/atomic/detail/ops_gcc_sync.hpp
+++ b/boost/atomic/detail/ops_gcc_sync.hpp
@@ -145,11 +145,6 @@ struct gcc_sync_operations :
if (order == memory_order_seq_cst)
__sync_synchronize();
}
-
- static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
- {
- return true;
- }
};
#if BOOST_ATOMIC_INT8_LOCK_FREE > 0
diff --git a/boost/atomic/detail/ops_gcc_x86.hpp b/boost/atomic/detail/ops_gcc_x86.hpp
index 98dcdc064e..74e45c1f61 100644
--- a/boost/atomic/detail/ops_gcc_x86.hpp
+++ b/boost/atomic/detail/ops_gcc_x86.hpp
@@ -104,11 +104,6 @@ struct gcc_x86_operations :
{
store(storage, (storage_type)0, order);
}
-
- static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
- {
- return true;
- }
};
template< bool Signed >
diff --git a/boost/atomic/detail/ops_gcc_x86_dcas.hpp b/boost/atomic/detail/ops_gcc_x86_dcas.hpp
index e356e8cfbd..7f3962199a 100644
--- a/boost/atomic/detail/ops_gcc_x86_dcas.hpp
+++ b/boost/atomic/detail/ops_gcc_x86_dcas.hpp
@@ -354,11 +354,6 @@ struct gcc_dcas_x86
#endif // defined(__PIC__)
#endif
}
-
- static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
- {
- return true;
- }
};
#endif // defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B)
@@ -611,11 +606,6 @@ struct gcc_dcas_x86_64
return v;
#endif
}
-
- static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
- {
- return true;
- }
};
#endif // defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
diff --git a/boost/atomic/detail/ops_linux_arm.hpp b/boost/atomic/detail/ops_linux_arm.hpp
index 01894b63ee..c26bc2c07b 100644
--- a/boost/atomic/detail/ops_linux_arm.hpp
+++ b/boost/atomic/detail/ops_linux_arm.hpp
@@ -136,11 +136,6 @@ struct linux_arm_cas :
return false;
}
}
-
- static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
- {
- return true;
- }
};
template< bool Signed >
diff --git a/boost/atomic/detail/ops_msvc_arm.hpp b/boost/atomic/detail/ops_msvc_arm.hpp
index fd07f093fb..e0a709c991 100644
--- a/boost/atomic/detail/ops_msvc_arm.hpp
+++ b/boost/atomic/detail/ops_msvc_arm.hpp
@@ -18,11 +18,11 @@
#include <intrin.h>
#include <boost/memory_order.hpp>
-#include <boost/type_traits/make_signed.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/interlocked.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
+#include <boost/atomic/detail/type_traits/make_signed.hpp>
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/detail/ops_msvc_common.hpp>
@@ -105,7 +105,7 @@ struct msvc_arm_operations :
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
- typedef typename make_signed< storage_type >::type signed_storage_type;
+ typedef typename boost::atomics::detail::make_signed< storage_type >::type signed_storage_type;
return Derived::fetch_add(storage, static_cast< storage_type >(-static_cast< signed_storage_type >(v)), order);
}
@@ -124,11 +124,6 @@ struct msvc_arm_operations :
{
Derived::store(storage, (storage_type)0, order);
}
-
- static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
- {
- return true;
- }
};
template< bool Signed >
diff --git a/boost/atomic/detail/ops_msvc_x86.hpp b/boost/atomic/detail/ops_msvc_x86.hpp
index 24824214dd..623662468d 100644
--- a/boost/atomic/detail/ops_msvc_x86.hpp
+++ b/boost/atomic/detail/ops_msvc_x86.hpp
@@ -17,11 +17,11 @@
#define BOOST_ATOMIC_DETAIL_OPS_MSVC_X86_HPP_INCLUDED_
#include <boost/memory_order.hpp>
-#include <boost/type_traits/make_signed.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/interlocked.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
+#include <boost/atomic/detail/type_traits/make_signed.hpp>
#include <boost/atomic/capabilities.hpp>
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
#include <boost/cstdint.hpp>
@@ -135,7 +135,7 @@ struct msvc_x86_operations :
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
- typedef typename make_signed< storage_type >::type signed_storage_type;
+ typedef typename boost::atomics::detail::make_signed< storage_type >::type signed_storage_type;
return Derived::fetch_add(storage, static_cast< storage_type >(-static_cast< signed_storage_type >(v)), order);
}
@@ -154,11 +154,6 @@ struct msvc_x86_operations :
{
store(storage, (storage_type)0, order);
}
-
- static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
- {
- return true;
- }
};
template< bool Signed >
@@ -799,11 +794,6 @@ struct msvc_dcas_x86
return v;
}
-
- static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
- {
- return true;
- }
};
template< bool Signed >
@@ -893,11 +883,6 @@ struct msvc_dcas_x86_64
{
return compare_exchange_strong(storage, expected, desired, success_order, failure_order);
}
-
- static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
- {
- return true;
- }
};
template< bool Signed >
diff --git a/boost/atomic/detail/ops_windows.hpp b/boost/atomic/detail/ops_windows.hpp
index 867f1c6113..50d951dabf 100644
--- a/boost/atomic/detail/ops_windows.hpp
+++ b/boost/atomic/detail/ops_windows.hpp
@@ -24,11 +24,11 @@
#define BOOST_ATOMIC_DETAIL_OPS_WINDOWS_HPP_INCLUDED_
#include <boost/memory_order.hpp>
-#include <boost/type_traits/make_signed.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/interlocked.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
+#include <boost/atomic/detail/type_traits/make_signed.hpp>
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/detail/ops_msvc_common.hpp>
#include <boost/atomic/detail/ops_extending_cas_based.hpp>
@@ -80,7 +80,7 @@ struct windows_operations :
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
- typedef typename make_signed< storage_type >::type signed_storage_type;
+ typedef typename boost::atomics::detail::make_signed< storage_type >::type signed_storage_type;
return Derived::fetch_add(storage, static_cast< storage_type >(-static_cast< signed_storage_type >(v)), order);
}
@@ -99,11 +99,6 @@ struct windows_operations :
{
store(storage, (storage_type)0, order);
}
-
- static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
- {
- return true;
- }
};
template< bool Signed >
diff --git a/boost/atomic/detail/platform.hpp b/boost/atomic/detail/platform.hpp
index cc3cf1b67a..786b1f1971 100644
--- a/boost/atomic/detail/platform.hpp
+++ b/boost/atomic/detail/platform.hpp
@@ -60,7 +60,8 @@
defined(__ARM_ARCH_6ZK__) ||\
defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) ||\
defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) ||\
- defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7S__)\
+ defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7S__) ||\
+ defined(__ARM_ARCH_8A__)\
)
#define BOOST_ATOMIC_DETAIL_PLATFORM gcc_arm
diff --git a/boost/atomic/detail/storage_type.hpp b/boost/atomic/detail/storage_type.hpp
index 63a7cef581..59e6901c26 100644
--- a/boost/atomic/detail/storage_type.hpp
+++ b/boost/atomic/detail/storage_type.hpp
@@ -38,7 +38,7 @@ BOOST_FORCEINLINE void non_atomic_load(T const volatile& from, T& to) BOOST_NOEX
}
template< std::size_t Size >
-struct buffer_storage
+struct BOOST_ATOMIC_DETAIL_MAY_ALIAS buffer_storage
{
BOOST_ALIGNMENT(16) unsigned char data[Size];
@@ -69,7 +69,7 @@ struct make_storage_type
{
typedef buffer_storage< Size > type;
- struct aligned
+ struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned
{
type value;
@@ -81,9 +81,9 @@ struct make_storage_type
template< >
struct make_storage_type< 1u, false >
{
- typedef boost::uint8_t type;
+ typedef boost::uint8_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type;
- struct aligned
+ struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned
{
type value;
@@ -95,9 +95,9 @@ struct make_storage_type< 1u, false >
template< >
struct make_storage_type< 1u, true >
{
- typedef boost::int8_t type;
+ typedef boost::int8_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type;
- struct aligned
+ struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned
{
type value;
@@ -109,9 +109,9 @@ struct make_storage_type< 1u, true >
template< >
struct make_storage_type< 2u, false >
{
- typedef boost::uint16_t type;
+ typedef boost::uint16_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type;
- struct aligned
+ struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned
{
BOOST_ALIGNMENT(2) type value;
@@ -123,9 +123,9 @@ struct make_storage_type< 2u, false >
template< >
struct make_storage_type< 2u, true >
{
- typedef boost::int16_t type;
+ typedef boost::int16_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type;
- struct aligned
+ struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned
{
BOOST_ALIGNMENT(2) type value;
@@ -137,9 +137,9 @@ struct make_storage_type< 2u, true >
template< >
struct make_storage_type< 4u, false >
{
- typedef boost::uint32_t type;
+ typedef boost::uint32_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type;
- struct aligned
+ struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned
{
BOOST_ALIGNMENT(4) type value;
@@ -151,9 +151,9 @@ struct make_storage_type< 4u, false >
template< >
struct make_storage_type< 4u, true >
{
- typedef boost::int32_t type;
+ typedef boost::int32_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type;
- struct aligned
+ struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned
{
BOOST_ALIGNMENT(4) type value;
@@ -165,9 +165,9 @@ struct make_storage_type< 4u, true >
template< >
struct make_storage_type< 8u, false >
{
- typedef boost::uint64_t type;
+ typedef boost::uint64_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type;
- struct aligned
+ struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned
{
BOOST_ALIGNMENT(8) type value;
@@ -179,9 +179,9 @@ struct make_storage_type< 8u, false >
template< >
struct make_storage_type< 8u, true >
{
- typedef boost::int64_t type;
+ typedef boost::int64_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type;
- struct aligned
+ struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned
{
BOOST_ALIGNMENT(8) type value;
@@ -195,9 +195,9 @@ struct make_storage_type< 8u, true >
template< >
struct make_storage_type< 16u, false >
{
- typedef boost::uint128_type type;
+ typedef boost::uint128_type BOOST_ATOMIC_DETAIL_MAY_ALIAS type;
- struct aligned
+ struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned
{
BOOST_ALIGNMENT(16) type value;
@@ -209,9 +209,9 @@ struct make_storage_type< 16u, false >
template< >
struct make_storage_type< 16u, true >
{
- typedef boost::int128_type type;
+ typedef boost::int128_type BOOST_ATOMIC_DETAIL_MAY_ALIAS type;
- struct aligned
+ struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned
{
BOOST_ALIGNMENT(16) type value;
@@ -222,7 +222,7 @@ struct make_storage_type< 16u, true >
#elif !defined(BOOST_NO_ALIGNMENT)
-struct storage128_t
+struct BOOST_ATOMIC_DETAIL_MAY_ALIAS storage128_t
{
boost::uint64_t data[2];
@@ -252,7 +252,7 @@ struct make_storage_type< 16u, Signed >
{
typedef storage128_t type;
- struct aligned
+ struct BOOST_ATOMIC_DETAIL_MAY_ALIAS aligned
{
BOOST_ALIGNMENT(16) type value;
diff --git a/boost/atomic/detail/type_traits/conditional.hpp b/boost/atomic/detail/type_traits/conditional.hpp
new file mode 100644
index 0000000000..71397ab154
--- /dev/null
+++ b/boost/atomic/detail/type_traits/conditional.hpp
@@ -0,0 +1,42 @@
+/*
+ * Distributed under the 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 (c) 2017 Andrey Semashev
+ */
+/*!
+ * \file atomic/detail/type_traits/conditional.hpp
+ *
+ * This header defines \c conditional type trait
+ */
+
+#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_CONDITIONAL_HPP_INCLUDED_
+#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_CONDITIONAL_HPP_INCLUDED_
+
+#include <boost/atomic/detail/config.hpp>
+#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS)
+#include <type_traits>
+#else
+#include <boost/type_traits/conditional.hpp>
+#endif
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+namespace atomics {
+namespace detail {
+
+#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS)
+using std::conditional;
+#else
+using boost::conditional;
+#endif
+
+} // namespace detail
+} // namespace atomics
+} // namespace boost
+
+#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_CONDITIONAL_HPP_INCLUDED_
diff --git a/boost/atomic/detail/type_traits/is_function.hpp b/boost/atomic/detail/type_traits/is_function.hpp
new file mode 100644
index 0000000000..7b82840f5e
--- /dev/null
+++ b/boost/atomic/detail/type_traits/is_function.hpp
@@ -0,0 +1,42 @@
+/*
+ * Distributed under the 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 (c) 2017 Andrey Semashev
+ */
+/*!
+ * \file atomic/detail/type_traits/is_function.hpp
+ *
+ * This header defines \c is_function type trait
+ */
+
+#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_FUNCTION_HPP_INCLUDED_
+#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_FUNCTION_HPP_INCLUDED_
+
+#include <boost/atomic/detail/config.hpp>
+#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS)
+#include <type_traits>
+#else
+#include <boost/type_traits/is_function.hpp>
+#endif
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+namespace atomics {
+namespace detail {
+
+#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS)
+using std::is_function;
+#else
+using boost::is_function;
+#endif
+
+} // namespace detail
+} // namespace atomics
+} // namespace boost
+
+#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_FUNCTION_HPP_INCLUDED_
diff --git a/boost/atomic/detail/type_traits/is_integral.hpp b/boost/atomic/detail/type_traits/is_integral.hpp
new file mode 100644
index 0000000000..5deb12034c
--- /dev/null
+++ b/boost/atomic/detail/type_traits/is_integral.hpp
@@ -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)
+ *
+ * Copyright (c) 2017 Andrey Semashev
+ */
+/*!
+ * \file atomic/detail/type_traits/is_integral.hpp
+ *
+ * This header defines \c is_integral type trait
+ */
+
+#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_INTEGRAL_HPP_INCLUDED_
+#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_INTEGRAL_HPP_INCLUDED_
+
+#include <boost/atomic/detail/config.hpp>
+// Some versions of libstdc++ don't consider __int128 an integral type. Use Boost.TypeTraits because of that.
+#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128)
+#include <type_traits>
+#else
+#include <boost/type_traits/is_integral.hpp>
+#endif
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+namespace atomics {
+namespace detail {
+
+#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128)
+using std::is_integral;
+#else
+using boost::is_integral;
+#endif
+
+} // namespace detail
+} // namespace atomics
+} // namespace boost
+
+#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_INTEGRAL_HPP_INCLUDED_
diff --git a/boost/atomic/detail/type_traits/is_signed.hpp b/boost/atomic/detail/type_traits/is_signed.hpp
new file mode 100644
index 0000000000..bf95163828
--- /dev/null
+++ b/boost/atomic/detail/type_traits/is_signed.hpp
@@ -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)
+ *
+ * Copyright (c) 2017 Andrey Semashev
+ */
+/*!
+ * \file atomic/detail/type_traits/is_signed.hpp
+ *
+ * This header defines \c is_signed type trait
+ */
+
+#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_SIGNED_HPP_INCLUDED_
+#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_SIGNED_HPP_INCLUDED_
+
+#include <boost/atomic/detail/config.hpp>
+// Some versions of libstdc++ don't consider __int128 an integral type. Use Boost.TypeTraits because of that.
+#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128)
+#include <type_traits>
+#else
+#include <boost/type_traits/is_signed.hpp>
+#endif
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+namespace atomics {
+namespace detail {
+
+#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128)
+using std::is_signed;
+#else
+using boost::is_signed;
+#endif
+
+} // namespace detail
+} // namespace atomics
+} // namespace boost
+
+#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_SIGNED_HPP_INCLUDED_
diff --git a/boost/atomic/detail/type_traits/make_signed.hpp b/boost/atomic/detail/type_traits/make_signed.hpp
new file mode 100644
index 0000000000..831efdc391
--- /dev/null
+++ b/boost/atomic/detail/type_traits/make_signed.hpp
@@ -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)
+ *
+ * Copyright (c) 2017 Andrey Semashev
+ */
+/*!
+ * \file atomic/detail/type_traits/make_signed.hpp
+ *
+ * This header defines \c make_signed type trait
+ */
+
+#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_MAKE_SIGNED_HPP_INCLUDED_
+#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_MAKE_SIGNED_HPP_INCLUDED_
+
+#include <boost/atomic/detail/config.hpp>
+// Some versions of libstdc++ don't consider __int128 an integral type. Use Boost.TypeTraits because of that.
+#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128)
+#include <type_traits>
+#else
+#include <boost/type_traits/make_signed.hpp>
+#endif
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+namespace atomics {
+namespace detail {
+
+#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128)
+using std::make_signed;
+#else
+using boost::make_signed;
+#endif
+
+} // namespace detail
+} // namespace atomics
+} // namespace boost
+
+#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_MAKE_SIGNED_HPP_INCLUDED_
diff --git a/boost/chrono/duration.hpp b/boost/chrono/duration.hpp
index 737328c418..0a09674f1a 100644
--- a/boost/chrono/duration.hpp
+++ b/boost/chrono/duration.hpp
@@ -433,12 +433,13 @@ namespace chrono {
rep rep_;
public:
-#if defined BOOST_NO_CXX11_DEFAULTED_FUNCTIONS || \
- defined BOOST_CHRONO_DURATION_DEFAULTS_TO_ZERO
+#if defined BOOST_CHRONO_DURATION_DEFAULTS_TO_ZERO
BOOST_FORCEINLINE BOOST_CONSTEXPR
duration() : rep_(duration_values<rep>::zero()) { }
+#elif defined BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
+ BOOST_CONSTEXPR duration() {}
#else
- BOOST_CONSTEXPR duration() BOOST_NOEXCEPT : rep_() {};
+ BOOST_CONSTEXPR duration() = default;
#endif
template <class Rep2>
BOOST_SYMBOL_VISIBLE BOOST_FORCEINLINE BOOST_CONSTEXPR
@@ -542,8 +543,8 @@ namespace chrono {
const duration<Rep2, Period2>& rhs)
{
typedef typename common_type<duration<Rep1, Period1>,
- duration<Rep2, Period2> >::type CD;
- return CD(CD(lhs).count()+CD(rhs).count());
+ duration<Rep2, Period2> >::type common_duration;
+ return common_duration(common_duration(lhs).count()+common_duration(rhs).count());
}
// Duration -
@@ -555,8 +556,8 @@ namespace chrono {
const duration<Rep2, Period2>& rhs)
{
typedef typename common_type<duration<Rep1, Period1>,
- duration<Rep2, Period2> >::type CD;
- return CD(CD(lhs).count()-CD(rhs).count());
+ duration<Rep2, Period2> >::type common_duration;
+ return common_duration(common_duration(lhs).count()-common_duration(rhs).count());
}
// Duration *
@@ -572,9 +573,9 @@ namespace chrono {
>::type
operator*(const duration<Rep1, Period>& d, const Rep2& s)
{
- typedef typename common_type<Rep1, Rep2>::type CR;
- typedef duration<CR, Period> CD;
- return CD(CD(d).count()*static_cast<CR>(s));
+ typedef typename common_type<Rep1, Rep2>::type common_rep;
+ typedef duration<common_rep, Period> common_duration;
+ return common_duration(common_duration(d).count()*static_cast<common_rep>(s));
}
template <class Rep1, class Period, class Rep2>
@@ -601,10 +602,9 @@ namespace chrono {
>::type
operator/(const duration<Rep1, Period>& d, const Rep2& s)
{
- typedef typename common_type<Rep1, Rep2>::type CR;
- typedef duration<CR, Period> CD;
-
- return CD(CD(d).count()/static_cast<CR>(s));
+ typedef typename common_type<Rep1, Rep2>::type common_rep;
+ typedef duration<common_rep, Period> common_duration;
+ return common_duration(common_duration(d).count()/static_cast<common_rep>(s));
}
template <class Rep1, class Period1, class Rep2, class Period2>
@@ -613,8 +613,8 @@ namespace chrono {
operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
{
typedef typename common_type<duration<Rep1, Period1>,
- duration<Rep2, Period2> >::type CD;
- return CD(lhs).count() / CD(rhs).count();
+ duration<Rep2, Period2> >::type common_duration;
+ return common_duration(lhs).count() / common_duration(rhs).count();
}
#ifdef BOOST_CHRONO_EXTENSIONS
@@ -626,10 +626,9 @@ namespace chrono {
>::type
operator/(const Rep1& s, const duration<Rep2, Period>& d)
{
- typedef typename common_type<Rep1, Rep2>::type CR;
- typedef duration<CR, Period> CD;
-
- return static_cast<CR>(s)/CD(d).count();
+ typedef typename common_type<Rep1, Rep2>::type common_rep;
+ typedef duration<common_rep, Period> common_duration;
+ return static_cast<common_rep>(s)/common_duration(d).count();
}
#endif
// Duration %
@@ -642,10 +641,9 @@ namespace chrono {
>::type
operator%(const duration<Rep1, Period>& d, const Rep2& s)
{
- typedef typename common_type<Rep1, Rep2>::type CR;
- typedef duration<CR, Period> CD;
-
- return CD(CD(d).count()%static_cast<CR>(s));
+ typedef typename common_type<Rep1, Rep2>::type common_rep;
+ typedef duration<common_rep, Period> common_duration;
+ return common_duration(common_duration(d).count()%static_cast<common_rep>(s));
}
template <class Rep1, class Period1, class Rep2, class Period2>
@@ -654,9 +652,9 @@ namespace chrono {
operator%(const duration<Rep1, Period1>& lhs,
const duration<Rep2, Period2>& rhs) {
typedef typename common_type<duration<Rep1, Period1>,
- duration<Rep2, Period2> >::type CD;
+ duration<Rep2, Period2> >::type common_duration;
- return CD(CD(lhs).count()%CD(rhs).count());
+ return common_duration(common_duration(lhs).count()%common_duration(rhs).count());
}
@@ -671,8 +669,8 @@ namespace detail
{
BOOST_CONSTEXPR bool operator()(const LhsDuration& lhs, const RhsDuration& rhs) const
{
- typedef typename common_type<LhsDuration, RhsDuration>::type CD;
- return CD(lhs).count() == CD(rhs).count();
+ typedef typename common_type<LhsDuration, RhsDuration>::type common_duration;
+ return common_duration(lhs).count() == common_duration(rhs).count();
}
};
@@ -690,8 +688,8 @@ namespace detail
{
BOOST_CONSTEXPR bool operator()(const LhsDuration& lhs, const RhsDuration& rhs) const
{
- typedef typename common_type<LhsDuration, RhsDuration>::type CD;
- return CD(lhs).count() < CD(rhs).count();
+ typedef typename common_type<LhsDuration, RhsDuration>::type common_duration;
+ return common_duration(lhs).count() < common_duration(rhs).count();
}
};
diff --git a/boost/chrono/io/duration_io.hpp b/boost/chrono/io/duration_io.hpp
index 34004484f3..f3aca6adfd 100644
--- a/boost/chrono/io/duration_io.hpp
+++ b/boost/chrono/io/duration_io.hpp
@@ -21,7 +21,7 @@
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_floating_point.hpp>
#include <locale>
-#include <iostream>
+#include <iosfwd>
#include <sstream>
namespace boost
diff --git a/boost/chrono/io/time_point_io.hpp b/boost/chrono/io/time_point_io.hpp
index 0cbc275c0e..ef51210bd8 100644
--- a/boost/chrono/io/time_point_io.hpp
+++ b/boost/chrono/io/time_point_io.hpp
@@ -34,20 +34,22 @@
#include <locale>
#include <ctime>
-#define BOOST_CHRONO_INTERNAL_TIMEGM \
- ( defined BOOST_WINDOWS && ! defined(__CYGWIN__) ) \
+#if ( defined BOOST_WINDOWS && ! defined(__CYGWIN__) ) \
|| (defined(sun) || defined(__sun)) \
|| (defined __IBMCPP__) \
|| defined __ANDROID__ \
|| defined __QNXNTO__ \
|| (defined(_AIX) && defined __GNUC__)
+#define BOOST_CHRONO_INTERNAL_TIMEGM
+#endif
-#define BOOST_CHRONO_INTERNAL_GMTIME \
- (defined BOOST_WINDOWS && ! defined(__CYGWIN__)) \
+#if (defined BOOST_WINDOWS && ! defined(__CYGWIN__)) \
|| ( (defined(sun) || defined(__sun)) && defined __GNUC__) \
|| (defined __IBMCPP__) \
|| defined __ANDROID__ \
|| (defined(_AIX) && defined __GNUC__)
+#define BOOST_CHRONO_INTERNAL_GMTIME
+#endif
#define BOOST_CHRONO_USES_INTERNAL_TIME_GET
@@ -746,7 +748,7 @@ namespace boost
namespace detail
{
-//#if BOOST_CHRONO_INTERNAL_TIMEGM
+//#if defined BOOST_CHRONO_INTERNAL_TIMEGM
inline int32_t is_leap(int32_t year)
{
@@ -949,7 +951,7 @@ namespace boost
}
else
{
-#if BOOST_CHRONO_INTERNAL_GMTIME
+#if defined BOOST_CHRONO_INTERNAL_GMTIME
if (detail::internal_gmtime(&t, &tm) == 0) failed = true;
#elif defined BOOST_WINDOWS && ! defined(__CYGWIN__)
@@ -1157,7 +1159,7 @@ namespace boost
if (err & std::ios_base::failbit) goto exit;
time_t t;
-#if BOOST_CHRONO_INTERNAL_TIMEGM
+#if defined BOOST_CHRONO_INTERNAL_TIMEGM
t = detail::internal_timegm(&tm);
#else
t = timegm(&tm);
@@ -1209,7 +1211,7 @@ namespace boost
time_t t;
if (tz == timezone::utc || fz != pe)
{
-#if BOOST_CHRONO_INTERNAL_TIMEGM
+#if defined BOOST_CHRONO_INTERNAL_TIMEGM
t = detail::internal_timegm(&tm);
#else
t = timegm(&tm);
diff --git a/boost/chrono/io/time_point_units.hpp b/boost/chrono/io/time_point_units.hpp
index 7aef8526da..6a4999a5e5 100644
--- a/boost/chrono/io/time_point_units.hpp
+++ b/boost/chrono/io/time_point_units.hpp
@@ -15,7 +15,7 @@
#include <boost/chrono/thread_clock.hpp>
#include <boost/chrono/io/ios_base_state.hpp>
#include <string>
-#include <iostream>
+#include <iosfwd>
#include <ios>
#include <locale>
#include <algorithm>
diff --git a/boost/chrono/process_cpu_clocks.hpp b/boost/chrono/process_cpu_clocks.hpp
index ca6bef38e9..93d3c94ac8 100644
--- a/boost/chrono/process_cpu_clocks.hpp
+++ b/boost/chrono/process_cpu_clocks.hpp
@@ -20,7 +20,7 @@
#include <boost/chrono/time_point.hpp>
#include <boost/operators.hpp>
#include <boost/chrono/detail/system.hpp>
-#include <iostream>
+#include <iosfwd>
#include <boost/type_traits/common_type.hpp>
#include <boost/chrono/clock_string.hpp>
@@ -476,7 +476,7 @@ namespace std {
(std::numeric_limits<Rep>::max)(),
(std::numeric_limits<Rep>::max)());
}
- static Res lowest() throw()
+ static Res lowest() BOOST_NOEXCEPT_OR_NOTHROW
{
return (min)();
}
diff --git a/boost/chrono/time_point.hpp b/boost/chrono/time_point.hpp
index 6449fac6e1..fc230955d9 100644
--- a/boost/chrono/time_point.hpp
+++ b/boost/chrono/time_point.hpp
@@ -31,7 +31,6 @@ time2_demo contained this comment:
#define BOOST_CHRONO_TIME_POINT_HPP
#include <boost/chrono/duration.hpp>
-#include <iostream>
#ifndef BOOST_CHRONO_HEADER_ONLY
// this must occur after all of the includes and before any code appears:
diff --git a/boost/circular_buffer/base.hpp b/boost/circular_buffer/base.hpp
index 1dec2f2136..4babd9fbb1 100644
--- a/boost/circular_buffer/base.hpp
+++ b/boost/circular_buffer/base.hpp
@@ -666,7 +666,7 @@ public:
break;
}
if (is_uninitialized(dest)) {
- boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*dest), boost::move_if_noexcept(*src));
+ boost::container::allocator_traits<Alloc>::construct(m_alloc, cb_details::to_address(dest), boost::move_if_noexcept(*src));
++constructed;
} else {
value_type tmp = boost::move_if_noexcept(*src);
@@ -1422,7 +1422,7 @@ private:
increment(m_last);
m_first = m_last;
} else {
- boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*m_last), static_cast<ValT>(item));
+ boost::container::allocator_traits<Alloc>::construct(m_alloc, cb_details::to_address(m_last), static_cast<ValT>(item));
increment(m_last);
++m_size;
}
@@ -1439,7 +1439,7 @@ private:
m_last = m_first;
} else {
decrement(m_first);
- boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*m_first), static_cast<ValT>(item));
+ boost::container::allocator_traits<Alloc>::construct(m_alloc, cb_details::to_address(m_first), static_cast<ValT>(item));
++m_size;
}
} BOOST_CATCH(...) {
@@ -2414,7 +2414,7 @@ private:
*/
void construct_or_replace(bool construct, pointer pos, param_value_type item) {
if (construct)
- boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*pos), item);
+ boost::container::allocator_traits<Alloc>::construct(m_alloc, cb_details::to_address(pos), item);
else
replace(pos, item);
}
@@ -2426,14 +2426,14 @@ private:
*/
void construct_or_replace(bool construct, pointer pos, rvalue_type item) {
if (construct)
- boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*pos), boost::move(item));
+ boost::container::allocator_traits<Alloc>::construct(m_alloc, cb_details::to_address(pos), boost::move(item));
else
replace(pos, boost::move(item));
}
//! Destroy an item.
void destroy_item(pointer p) {
- boost::container::allocator_traits<Alloc>::destroy(m_alloc, boost::addressof(*p));
+ boost::container::allocator_traits<Alloc>::destroy(m_alloc, cb_details::to_address(p));
#if BOOST_CB_ENABLE_DEBUG
invalidate_iterators(iterator(this, p));
cb_details::do_fill_uninitialized_memory(p, sizeof(value_type));
@@ -2566,7 +2566,7 @@ private:
if (buffer_capacity == 0)
return;
while (first != last && !full()) {
- boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*m_last), *first++);
+ boost::container::allocator_traits<Alloc>::construct(m_alloc, cb_details::to_address(m_last), *first++);
increment(m_last);
++m_size;
}
@@ -2831,7 +2831,7 @@ private:
pointer p = m_last;
BOOST_TRY {
for (; ii < construct; ++ii, increment(p))
- boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*p), *wrapper());
+ boost::container::allocator_traits<Alloc>::construct(m_alloc, cb_details::to_address(p), *wrapper());
for (;ii < n; ++ii, increment(p))
replace(p, *wrapper());
} BOOST_CATCH(...) {
@@ -2925,7 +2925,7 @@ private:
for (;ii > construct; --ii, increment(p))
replace(p, *wrapper());
for (; ii > 0; --ii, increment(p))
- boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*p), *wrapper());
+ boost::container::allocator_traits<Alloc>::construct(m_alloc, cb_details::to_address(p), *wrapper());
} BOOST_CATCH(...) {
size_type constructed = ii < construct ? construct - ii : 0;
m_last = add(m_last, constructed);
diff --git a/boost/circular_buffer/details.hpp b/boost/circular_buffer/details.hpp
index 3262386acf..13747823ab 100644
--- a/boost/circular_buffer/details.hpp
+++ b/boost/circular_buffer/details.hpp
@@ -1,7 +1,7 @@
// Helper classes and functions for the circular buffer.
// Copyright (c) 2003-2008 Jan Gaspar
-// Copyright (c) 2014 Glen Fernandes // C++11 allocator model support.
+// Copyright (c) 2014 Glen Joseph Fernandes // C++11 allocator model support.
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -16,6 +16,7 @@
#include <boost/throw_exception.hpp>
#include <boost/container/allocator_traits.hpp>
+#include <boost/core/pointer_traits.hpp>
#include <boost/move/move.hpp>
#include <boost/type_traits/is_nothrow_move_constructible.hpp>
#include <boost/utility/addressof.hpp>
@@ -34,6 +35,13 @@ namespace boost {
namespace cb_details {
+template<class Pointer>
+inline typename boost::pointer_traits<Pointer>::element_type*
+to_address(Pointer p) BOOST_NOEXCEPT
+{
+ return boost::pointer_traits<Pointer>::to_address(p);
+}
+
template <class Traits> struct nonconst_traits;
template<class ForwardIterator, class Diff, class T, class Alloc>
@@ -435,10 +443,10 @@ inline ForwardIterator uninitialized_copy(InputIterator first, InputIterator las
ForwardIterator next = dest;
BOOST_TRY {
for (; first != last; ++first, ++dest)
- boost::container::allocator_traits<Alloc>::construct(a, boost::addressof(*dest), *first);
+ boost::container::allocator_traits<Alloc>::construct(a, cb_details::to_address(dest), *first);
} BOOST_CATCH(...) {
for (; next != dest; ++next)
- boost::container::allocator_traits<Alloc>::destroy(a, boost::addressof(*next));
+ boost::container::allocator_traits<Alloc>::destroy(a, cb_details::to_address(next));
BOOST_RETHROW
}
BOOST_CATCH_END
@@ -449,7 +457,7 @@ template<class InputIterator, class ForwardIterator, class Alloc>
ForwardIterator uninitialized_move_if_noexcept_impl(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a,
true_type) {
for (; first != last; ++first, ++dest)
- boost::container::allocator_traits<Alloc>::construct(a, boost::addressof(*dest), boost::move(*first));
+ boost::container::allocator_traits<Alloc>::construct(a, cb_details::to_address(dest), boost::move(*first));
return dest;
}
@@ -478,10 +486,10 @@ inline void uninitialized_fill_n_with_alloc(ForwardIterator first, Diff n, const
ForwardIterator next = first;
BOOST_TRY {
for (; n > 0; ++first, --n)
- boost::container::allocator_traits<Alloc>::construct(alloc, boost::addressof(*first), item);
+ boost::container::allocator_traits<Alloc>::construct(alloc, cb_details::to_address(first), item);
} BOOST_CATCH(...) {
for (; next != first; ++next)
- boost::container::allocator_traits<Alloc>::destroy(alloc, boost::addressof(*next));
+ boost::container::allocator_traits<Alloc>::destroy(alloc, cb_details::to_address(next));
BOOST_RETHROW
}
BOOST_CATCH_END
diff --git a/boost/compute/algorithm/accumulate.hpp b/boost/compute/algorithm/accumulate.hpp
index 328420a07c..be20bee60e 100644
--- a/boost/compute/algorithm/accumulate.hpp
+++ b/boost/compute/algorithm/accumulate.hpp
@@ -26,6 +26,7 @@ namespace boost {
namespace compute {
namespace detail {
+// Space complexity O(1)
template<class InputIterator, class T, class BinaryFunction>
inline T generic_accumulate(InputIterator first,
InputIterator last,
@@ -155,6 +156,9 @@ inline T dispatch_accumulate(InputIterator first,
/// reduce(vec.begin(), vec.end(), &result, plus<float>()); // fast
/// \endcode
///
+/// Space complexity: \Omega(1)<br>
+/// Space complexity when optimized to \c reduce(): \Omega(n)
+///
/// \see reduce()
template<class InputIterator, class T, class BinaryFunction>
inline T accumulate(InputIterator first,
diff --git a/boost/compute/algorithm/adjacent_difference.hpp b/boost/compute/algorithm/adjacent_difference.hpp
index ef13970754..c3b0e7d191 100644
--- a/boost/compute/algorithm/adjacent_difference.hpp
+++ b/boost/compute/algorithm/adjacent_difference.hpp
@@ -64,6 +64,9 @@ dispatch_adjacent_difference(InputIterator first,
///
/// \return \c OutputIterator to the end of the result range
///
+/// Space complexity: \Omega(1)<br>
+/// Space complexity when \p result == \p first: \Omega(n)
+///
/// \see adjacent_find()
template<class InputIterator, class OutputIterator, class BinaryFunction>
inline OutputIterator
diff --git a/boost/compute/algorithm/adjacent_find.hpp b/boost/compute/algorithm/adjacent_find.hpp
index 992a01eddc..a71a817f57 100644
--- a/boost/compute/algorithm/adjacent_find.hpp
+++ b/boost/compute/algorithm/adjacent_find.hpp
@@ -114,6 +114,8 @@ adjacent_find_with_atomics(InputIterator first,
/// \return \c InputIteratorm to the first element which compares equal
/// to the following element. If none are equal, returns \c last.
///
+/// Space complexity: \Omega(1)
+///
/// \see find(), adjacent_difference()
template<class InputIterator, class Compare>
inline InputIterator
diff --git a/boost/compute/algorithm/all_of.hpp b/boost/compute/algorithm/all_of.hpp
index 34d7518f32..56c5809992 100644
--- a/boost/compute/algorithm/all_of.hpp
+++ b/boost/compute/algorithm/all_of.hpp
@@ -20,6 +20,8 @@ namespace compute {
/// Returns \c true if \p predicate returns \c true for all of the elements in
/// the range [\p first, \p last).
///
+/// Space complexity: \Omega(1)
+///
/// \see any_of(), none_of()
template<class InputIterator, class UnaryPredicate>
inline bool all_of(InputIterator first,
diff --git a/boost/compute/algorithm/any_of.hpp b/boost/compute/algorithm/any_of.hpp
index b07779597c..54031fbac5 100644
--- a/boost/compute/algorithm/any_of.hpp
+++ b/boost/compute/algorithm/any_of.hpp
@@ -24,6 +24,8 @@ namespace compute {
///
/// \snippet test/test_any_all_none_of.cpp any_of
///
+/// Space complexity: \Omega(1)
+///
/// \see all_of(), none_of()
template<class InputIterator, class UnaryPredicate>
inline bool any_of(InputIterator first,
diff --git a/boost/compute/algorithm/binary_search.hpp b/boost/compute/algorithm/binary_search.hpp
index 6e19498790..880f3628fb 100644
--- a/boost/compute/algorithm/binary_search.hpp
+++ b/boost/compute/algorithm/binary_search.hpp
@@ -20,6 +20,8 @@ namespace compute {
/// Returns \c true if \p value is in the sorted range [\p first,
/// \p last).
+///
+/// Space complexity: \Omega(1)
template<class InputIterator, class T>
inline bool binary_search(InputIterator first,
InputIterator last,
diff --git a/boost/compute/algorithm/copy.hpp b/boost/compute/algorithm/copy.hpp
index 7779277b82..4866726f6e 100644
--- a/boost/compute/algorithm/copy.hpp
+++ b/boost/compute/algorithm/copy.hpp
@@ -826,6 +826,8 @@ dispatch_copy(InputIterator first,
/// );
/// \endcode
///
+/// Space complexity: \Omega(1)
+///
/// \see copy_n(), copy_if(), copy_async()
template<class InputIterator, class OutputIterator>
inline OutputIterator copy(InputIterator first,
diff --git a/boost/compute/algorithm/copy_if.hpp b/boost/compute/algorithm/copy_if.hpp
index 3cd08ef293..bdedcb8536 100644
--- a/boost/compute/algorithm/copy_if.hpp
+++ b/boost/compute/algorithm/copy_if.hpp
@@ -38,6 +38,8 @@ inline OutputIterator copy_index_if(InputIterator first,
/// Copies each element in the range [\p first, \p last) for which
/// \p predicate returns \c true to the range beginning at \p result.
+///
+/// Space complexity: \Omega(2n)
template<class InputIterator, class OutputIterator, class Predicate>
inline OutputIterator copy_if(InputIterator first,
InputIterator last,
diff --git a/boost/compute/algorithm/copy_n.hpp b/boost/compute/algorithm/copy_n.hpp
index f0989edc67..5280193497 100644
--- a/boost/compute/algorithm/copy_n.hpp
+++ b/boost/compute/algorithm/copy_n.hpp
@@ -30,6 +30,8 @@ namespace compute {
/// boost::compute::copy_n(values, 4, vec.begin(), queue);
/// \endcode
///
+/// Space complexity: \Omega(1)
+///
/// \see copy()
template<class InputIterator, class Size, class OutputIterator>
inline OutputIterator copy_n(InputIterator first,
diff --git a/boost/compute/algorithm/count.hpp b/boost/compute/algorithm/count.hpp
index 140d67379f..7a502c6791 100644
--- a/boost/compute/algorithm/count.hpp
+++ b/boost/compute/algorithm/count.hpp
@@ -23,6 +23,9 @@ namespace compute {
/// Returns the number of occurrences of \p value in the range
/// [\p first, \p last).
///
+/// Space complexity on CPUs: \Omega(1)<br>
+/// Space complexity on GPUs: \Omega(n)
+///
/// \see count_if()
template<class InputIterator, class T>
inline size_t count(InputIterator first,
diff --git a/boost/compute/algorithm/count_if.hpp b/boost/compute/algorithm/count_if.hpp
index c9381ce5d4..81996dc828 100644
--- a/boost/compute/algorithm/count_if.hpp
+++ b/boost/compute/algorithm/count_if.hpp
@@ -25,6 +25,9 @@ namespace compute {
/// Returns the number of elements in the range [\p first, \p last)
/// for which \p predicate returns \c true.
+///
+/// Space complexity on CPUs: \Omega(1)<br>
+/// Space complexity on GPUs: \Omega(n)
template<class InputIterator, class Predicate>
inline size_t count_if(InputIterator first,
InputIterator last,
diff --git a/boost/compute/algorithm/detail/copy_on_device.hpp b/boost/compute/algorithm/detail/copy_on_device.hpp
index 8738c8c0b4..034b3bc212 100644
--- a/boost/compute/algorithm/detail/copy_on_device.hpp
+++ b/boost/compute/algorithm/detail/copy_on_device.hpp
@@ -144,7 +144,7 @@ inline future<OutputIterator> copy_on_device_async(InputIterator first,
return make_future(result + std::distance(first, last), event_);
}
-#ifdef CL_VERSION_2_0
+#ifdef BOOST_COMPUTE_CL_VERSION_2_0
// copy_on_device() specialization for svm_ptr
template<class T>
inline svm_ptr<T> copy_on_device(svm_ptr<T> first,
@@ -181,7 +181,7 @@ inline future<svm_ptr<T> > copy_on_device_async(svm_ptr<T> first,
return make_future(result + count, event_);
}
-#endif // CL_VERSION_2_0
+#endif // BOOST_COMPUTE_CL_VERSION_2_0
} // end detail namespace
} // end compute namespace
diff --git a/boost/compute/algorithm/detail/copy_to_device.hpp b/boost/compute/algorithm/detail/copy_to_device.hpp
index bce5975f53..8601bb20ec 100644
--- a/boost/compute/algorithm/detail/copy_to_device.hpp
+++ b/boost/compute/algorithm/detail/copy_to_device.hpp
@@ -124,7 +124,7 @@ inline future<DeviceIterator> copy_to_device_async(HostIterator first,
return make_future(result + static_cast<difference_type>(count), event_);
}
-#ifdef CL_VERSION_2_0
+#ifdef BOOST_COMPUTE_CL_VERSION_2_0
// copy_to_device() specialization for svm_ptr
template<class HostIterator, class T>
inline svm_ptr<T> copy_to_device(HostIterator first,
@@ -184,7 +184,7 @@ inline svm_ptr<T> copy_to_device_map(HostIterator first,
return result + count;
}
-#endif // CL_VERSION_2_0
+#endif // BOOST_COMPUTE_CL_VERSION_2_0
} // end detail namespace
} // end compute namespace
diff --git a/boost/compute/algorithm/detail/copy_to_host.hpp b/boost/compute/algorithm/detail/copy_to_host.hpp
index d770a996ef..89b57174fa 100644
--- a/boost/compute/algorithm/detail/copy_to_host.hpp
+++ b/boost/compute/algorithm/detail/copy_to_host.hpp
@@ -125,7 +125,7 @@ inline future<HostIterator> copy_to_host_async(DeviceIterator first,
return make_future(iterator_plus_distance(result, count), event_);
}
-#ifdef CL_VERSION_2_0
+#ifdef BOOST_COMPUTE_CL_VERSION_2_0
// copy_to_host() specialization for svm_ptr
template<class T, class HostIterator>
inline HostIterator copy_to_host(svm_ptr<T> first,
@@ -189,7 +189,7 @@ inline HostIterator copy_to_host_map(svm_ptr<T> first,
return iterator_plus_distance(result, count);
}
-#endif // CL_VERSION_2_0
+#endif // BOOST_COMPUTE_CL_VERSION_2_0
} // end detail namespace
} // end compute namespace
diff --git a/boost/compute/algorithm/detail/find_extrema.hpp b/boost/compute/algorithm/detail/find_extrema.hpp
index eef2e36c3c..734b75aa90 100644
--- a/boost/compute/algorithm/detail/find_extrema.hpp
+++ b/boost/compute/algorithm/detail/find_extrema.hpp
@@ -56,7 +56,7 @@ inline InputIterator find_extrema(InputIterator first,
// use serial method for OpenCL version 1.0 due to
// problems with atomic_cmpxchg()
- #ifndef CL_VERSION_1_1
+ #ifndef BOOST_COMPUTE_CL_VERSION_1_1
return serial_find_extrema(first, last, compare, find_minimum, queue);
#endif
diff --git a/boost/compute/algorithm/detail/find_extrema_with_reduce.hpp b/boost/compute/algorithm/detail/find_extrema_with_reduce.hpp
index 8f2a83c38b..515d7cc6da 100644
--- a/boost/compute/algorithm/detail/find_extrema_with_reduce.hpp
+++ b/boost/compute/algorithm/detail/find_extrema_with_reduce.hpp
@@ -246,6 +246,7 @@ inline void find_extrema_with_reduce(InputIterator input,
);
}
+// Space complexity: \Omega(2 * work-group-size * work-groups-per-compute-unit)
template<class InputIterator, class Compare>
InputIterator find_extrema_with_reduce(InputIterator first,
InputIterator last,
diff --git a/boost/compute/algorithm/detail/find_if_with_atomics.hpp b/boost/compute/algorithm/detail/find_if_with_atomics.hpp
index 112c34cf00..e14fd12ae0 100644
--- a/boost/compute/algorithm/detail/find_if_with_atomics.hpp
+++ b/boost/compute/algorithm/detail/find_if_with_atomics.hpp
@@ -153,6 +153,7 @@ inline InputIterator find_if_with_atomics_multiple_vpt(InputIterator first,
return first + static_cast<difference_type>(index.read(queue));
}
+// Space complexity: O(1)
template<class InputIterator, class UnaryPredicate>
inline InputIterator find_if_with_atomics(InputIterator first,
InputIterator last,
diff --git a/boost/compute/algorithm/detail/merge_sort_on_gpu.hpp b/boost/compute/algorithm/detail/merge_sort_on_gpu.hpp
index e62c6beb8d..d5e1a2d8c9 100644
--- a/boost/compute/algorithm/detail/merge_sort_on_gpu.hpp
+++ b/boost/compute/algorithm/detail/merge_sort_on_gpu.hpp
@@ -91,6 +91,7 @@ inline size_t bitonic_block_sort(KeyIterator keys_first,
command_queue &queue)
{
typedef typename std::iterator_traits<KeyIterator>::value_type key_type;
+ typedef typename std::iterator_traits<ValueIterator>::value_type value_type;
meta_kernel k("bitonic_block_sort");
size_t count_arg = k.add_arg<const uint_>("count");
@@ -249,8 +250,11 @@ inline size_t bitonic_block_sort(KeyIterator keys_first,
k.var<key_type>("my_key") << ";\n";
if(sort_by_key)
{
- k << values_first[k.var<const uint_>("gid")] << " = " <<
- values_first[k.var<const uint_>("offset + my_index")] << ";\n";
+ k <<
+ k.decl<value_type>("my_value") << " = " <<
+ values_first[k.var<const uint_>("offset + my_index")] << ";\n" <<
+ "barrier(CLK_GLOBAL_MEM_FENCE);\n" <<
+ values_first[k.var<const uint_>("gid")] << " = my_value;\n";
}
k <<
// end if
@@ -418,7 +422,7 @@ inline void merge_blocks_on_gpu(KeyIterator keys_first,
");\n" <<
"left_idx = equal ? mid_idx + 1 : left_idx + 1;\n" <<
"right_idx = equal ? right_idx : mid_idx;\n" <<
- "upper_key = equal ? upper_key : " <<
+ "upper_key = " <<
keys_first[k.var<const uint_>("left_idx")] << ";\n" <<
"}\n" <<
"}\n" <<
diff --git a/boost/compute/algorithm/detail/radix_sort.hpp b/boost/compute/algorithm/detail/radix_sort.hpp
index 8e6d5f9c0a..53b1205c70 100644
--- a/boost/compute/algorithm/detail/radix_sort.hpp
+++ b/boost/compute/algorithm/detail/radix_sort.hpp
@@ -17,6 +17,9 @@
#include <boost/type_traits/is_signed.hpp>
#include <boost/type_traits/is_floating_point.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/not.hpp>
+
#include <boost/compute/kernel.hpp>
#include <boost/compute/program.hpp>
#include <boost/compute/command_queue.hpp>
@@ -305,9 +308,12 @@ inline void radix_sort_impl(const buffer_iterator<T> first,
options << " -DASC";
}
+ // get type definition if it is a custom struct
+ std::string custom_type_def = boost::compute::type_definition<T2>() + "\n";
+
// load radix sort program
program radix_sort_program = cache->get_or_build(
- cache_key, options.str(), radix_sort_source, context
+ cache_key, options.str(), custom_type_def + radix_sort_source, context
);
kernel count_kernel(radix_sort_program, "count");
diff --git a/boost/compute/algorithm/detail/serial_reduce.hpp b/boost/compute/algorithm/detail/serial_reduce.hpp
index 53aaf140fe..8b121274b9 100644
--- a/boost/compute/algorithm/detail/serial_reduce.hpp
+++ b/boost/compute/algorithm/detail/serial_reduce.hpp
@@ -20,6 +20,7 @@ namespace boost {
namespace compute {
namespace detail {
+// Space complexity: O(1)
template<class InputIterator, class OutputIterator, class BinaryFunction>
inline void serial_reduce(InputIterator first,
InputIterator last,
diff --git a/boost/compute/algorithm/detail/serial_reduce_by_key.hpp b/boost/compute/algorithm/detail/serial_reduce_by_key.hpp
index f9bda8e476..6fb04baa6d 100644
--- a/boost/compute/algorithm/detail/serial_reduce_by_key.hpp
+++ b/boost/compute/algorithm/detail/serial_reduce_by_key.hpp
@@ -55,11 +55,9 @@ inline size_t serial_reduce_by_key(InputKeyIterator keys_first,
size_t result_size_arg = k.add_arg<uint_ *>(memory_object::global_memory,
"result_size");
- convert<result_type> to_result_type;
-
k <<
k.decl<result_type>("result") <<
- " = " << to_result_type(values_first[0]) << ";\n" <<
+ " = " << values_first[0] << ";\n" <<
k.decl<key_type>("previous_key") << " = " << keys_first[0] << ";\n" <<
k.decl<result_type>("value") << ";\n" <<
k.decl<key_type>("key") << ";\n" <<
@@ -70,7 +68,7 @@ inline size_t serial_reduce_by_key(InputKeyIterator keys_first,
values_result[0] << " = result;\n" <<
"for(ulong i = 1; i < count; i++) {\n" <<
- " value = " << to_result_type(values_first[k.var<uint_>("i")]) << ";\n" <<
+ " value = " << values_first[k.var<uint_>("i")] << ";\n" <<
" key = " << keys_first[k.var<uint_>("i")] << ";\n" <<
" if (" << predicate(k.var<key_type>("previous_key"),
k.var<key_type>("key")) << ") {\n" <<
diff --git a/boost/compute/algorithm/equal.hpp b/boost/compute/algorithm/equal.hpp
index 35d0c5f0ea..c3c8053b71 100644
--- a/boost/compute/algorithm/equal.hpp
+++ b/boost/compute/algorithm/equal.hpp
@@ -20,6 +20,8 @@ namespace compute {
/// Returns \c true if the range [\p first1, \p last1) and the range
/// beginning at \p first2 are equal.
+///
+/// Space complexity: \Omega(1)
template<class InputIterator1, class InputIterator2>
inline bool equal(InputIterator1 first1,
InputIterator1 last1,
diff --git a/boost/compute/algorithm/equal_range.hpp b/boost/compute/algorithm/equal_range.hpp
index fd82177324..d7008e3cf4 100644
--- a/boost/compute/algorithm/equal_range.hpp
+++ b/boost/compute/algorithm/equal_range.hpp
@@ -23,6 +23,8 @@ namespace compute {
/// Returns a pair of iterators containing the range of values equal
/// to \p value in the sorted range [\p first, \p last).
+///
+/// Space complexity: \Omega(1)
template<class InputIterator, class T>
inline std::pair<InputIterator, InputIterator>
equal_range(InputIterator first,
diff --git a/boost/compute/algorithm/exclusive_scan.hpp b/boost/compute/algorithm/exclusive_scan.hpp
index 205d3de658..806a172cf4 100644
--- a/boost/compute/algorithm/exclusive_scan.hpp
+++ b/boost/compute/algorithm/exclusive_scan.hpp
@@ -44,6 +44,10 @@ namespace compute {
///
/// \snippet test/test_scan.cpp exclusive_scan_int_multiplies
///
+/// Space complexity on GPUs: \Omega(n)<br>
+/// Space complexity on GPUs when \p first == \p result: \Omega(2n)<br>
+/// Space complexity on CPUs: \Omega(1)
+///
/// \see inclusive_scan()
template<class InputIterator, class OutputIterator, class T, class BinaryOperator>
inline OutputIterator
diff --git a/boost/compute/algorithm/fill.hpp b/boost/compute/algorithm/fill.hpp
index c711f46b94..646d8acda4 100644
--- a/boost/compute/algorithm/fill.hpp
+++ b/boost/compute/algorithm/fill.hpp
@@ -64,7 +64,7 @@ inline future<void> fill_async_with_copy(BufferIterator first,
);
}
-#if defined(CL_VERSION_1_2)
+#if defined(BOOST_COMPUTE_CL_VERSION_1_2)
// meta-function returing true if Iterator points to a range of values
// that can be filled using clEnqueueFillBuffer(). to meet this criteria
@@ -172,7 +172,7 @@ dispatch_fill_async(BufferIterator first,
return future<void>(event_);
}
-#ifdef CL_VERSION_2_0
+#ifdef BOOST_COMPUTE_CL_VERSION_2_0
// specializations for svm_ptr<T>
template<class T>
inline void dispatch_fill(svm_ptr<T> first,
@@ -205,7 +205,7 @@ inline future<void> dispatch_fill_async(svm_ptr<T> first,
return future<void>(event_);
}
-#endif // CL_VERSION_2_0
+#endif // BOOST_COMPUTE_CL_VERSION_2_0
// default implementations
template<class BufferIterator, class T>
@@ -251,7 +251,7 @@ inline future<void> dispatch_fill_async(BufferIterator first,
{
return fill_async_with_copy(first, count, value, queue);
}
-#endif // !defined(CL_VERSION_1_2)
+#endif // !defined(BOOST_COMPUTE_CL_VERSION_1_2)
} // end detail namespace
@@ -271,6 +271,8 @@ inline future<void> dispatch_fill_async(BufferIterator first,
/// boost::compute::fill(vec.begin(), vec.end(), 7, queue);
/// \endcode
///
+/// Space complexity: \Omega(1)
+///
/// \see boost::compute::fill_n()
template<class BufferIterator, class T>
inline void fill(BufferIterator first,
diff --git a/boost/compute/algorithm/fill_n.hpp b/boost/compute/algorithm/fill_n.hpp
index 18a8f706a5..6be2d280a6 100644
--- a/boost/compute/algorithm/fill_n.hpp
+++ b/boost/compute/algorithm/fill_n.hpp
@@ -20,6 +20,8 @@ namespace compute {
/// Fills the range [\p first, \p first + count) with \p value.
///
+/// Space complexity: \Omega(1)
+///
/// \see fill()
template<class BufferIterator, class Size, class T>
inline void fill_n(BufferIterator first,
diff --git a/boost/compute/algorithm/find.hpp b/boost/compute/algorithm/find.hpp
index ef3ebf0c47..a6225b8c99 100644
--- a/boost/compute/algorithm/find.hpp
+++ b/boost/compute/algorithm/find.hpp
@@ -22,6 +22,8 @@ namespace compute {
/// Returns an iterator pointing to the first element in the range
/// [\p first, \p last) that equals \p value.
+///
+/// Space complexity: \Omega(1)
template<class InputIterator, class T>
inline InputIterator find(InputIterator first,
InputIterator last,
diff --git a/boost/compute/algorithm/find_end.hpp b/boost/compute/algorithm/find_end.hpp
index 265a1da542..a0a1b2e8c9 100644
--- a/boost/compute/algorithm/find_end.hpp
+++ b/boost/compute/algorithm/find_end.hpp
@@ -26,8 +26,8 @@ namespace detail {
///
/// \brief Helper function for find_end
///
-/// Basically a copy of find_if which returns last occurence
-/// instead of first occurence
+/// Basically a copy of find_if which returns last occurrence
+/// instead of first occurrence
///
template<class InputIterator, class UnaryPredicate>
inline InputIterator find_end_helper(InputIterator first,
@@ -90,6 +90,8 @@ inline InputIterator find_end_helper(InputIterator first,
/// \param p_last Iterator pointing to end of pattern
/// \param queue Queue on which to execute
///
+/// Space complexity: \Omega(n)
+///
template<class TextIterator, class PatternIterator>
inline TextIterator find_end(TextIterator t_first,
TextIterator t_last,
diff --git a/boost/compute/algorithm/find_if.hpp b/boost/compute/algorithm/find_if.hpp
index db99cc0396..074b47e280 100644
--- a/boost/compute/algorithm/find_if.hpp
+++ b/boost/compute/algorithm/find_if.hpp
@@ -20,6 +20,8 @@ namespace compute {
/// Returns an iterator pointing to the first element in the range
/// [\p first, \p last) for which \p predicate returns \c true.
+///
+/// Space complexity: \Omega(1)
template<class InputIterator, class UnaryPredicate>
inline InputIterator find_if(InputIterator first,
InputIterator last,
diff --git a/boost/compute/algorithm/find_if_not.hpp b/boost/compute/algorithm/find_if_not.hpp
index 61de050d31..a008a99469 100644
--- a/boost/compute/algorithm/find_if_not.hpp
+++ b/boost/compute/algorithm/find_if_not.hpp
@@ -22,6 +22,8 @@ namespace compute {
/// Returns an iterator pointing to the first element in the range
/// [\p first, \p last) for which \p predicate returns \c false.
///
+/// Space complexity: \Omega(1)
+///
/// \see find_if()
template<class InputIterator, class UnaryPredicate>
inline InputIterator find_if_not(InputIterator first,
diff --git a/boost/compute/algorithm/for_each.hpp b/boost/compute/algorithm/for_each.hpp
index 3ed399e6e9..7afba2b5f5 100644
--- a/boost/compute/algorithm/for_each.hpp
+++ b/boost/compute/algorithm/for_each.hpp
@@ -45,6 +45,8 @@ struct for_each_kernel : public meta_kernel
/// Calls \p function on each element in the range [\p first, \p last).
///
+/// Space complexity: \Omega(1)
+///
/// \see transform()
template<class InputIterator, class UnaryFunction>
inline UnaryFunction for_each(InputIterator first,
diff --git a/boost/compute/algorithm/for_each_n.hpp b/boost/compute/algorithm/for_each_n.hpp
index d0be784bf7..77932ab209 100644
--- a/boost/compute/algorithm/for_each_n.hpp
+++ b/boost/compute/algorithm/for_each_n.hpp
@@ -19,6 +19,8 @@ namespace compute {
/// Calls \p function on each element in the range [\p first, \p first
/// \c + \p count).
///
+/// Space complexity: \Omega(1)
+///
/// \see for_each()
template<class InputIterator, class Size, class UnaryFunction>
inline UnaryFunction for_each_n(InputIterator first,
diff --git a/boost/compute/algorithm/gather.hpp b/boost/compute/algorithm/gather.hpp
index 24c5c727ae..62442587f7 100644
--- a/boost/compute/algorithm/gather.hpp
+++ b/boost/compute/algorithm/gather.hpp
@@ -62,6 +62,8 @@ private:
/// to the range beginning at \p result using the input values from the range
/// beginning at \p input.
///
+/// Space complexity: \Omega(1)
+///
/// \see scatter()
template<class InputIterator, class MapIterator, class OutputIterator>
inline void gather(MapIterator first,
diff --git a/boost/compute/algorithm/generate.hpp b/boost/compute/algorithm/generate.hpp
index c70a542683..9ac76a3dca 100644
--- a/boost/compute/algorithm/generate.hpp
+++ b/boost/compute/algorithm/generate.hpp
@@ -22,6 +22,8 @@ namespace compute {
/// Stores the result of \p generator for each element in the range
/// [\p first, \p last).
+///
+/// Space complexity: \Omega(1)
template<class OutputIterator, class Generator>
inline void generate(OutputIterator first,
OutputIterator last,
diff --git a/boost/compute/algorithm/generate_n.hpp b/boost/compute/algorithm/generate_n.hpp
index 6d8e607b64..066a831ddf 100644
--- a/boost/compute/algorithm/generate_n.hpp
+++ b/boost/compute/algorithm/generate_n.hpp
@@ -20,6 +20,8 @@ namespace compute {
/// Stores the result of \p generator for each element in the range
/// [\p first, \p first + \p count).
+///
+/// Space complexity: \Omega(1)
template<class OutputIterator, class Size, class Generator>
inline void generate_n(OutputIterator first,
Size count,
diff --git a/boost/compute/algorithm/includes.hpp b/boost/compute/algorithm/includes.hpp
index c4e7c793e7..cfef9540a7 100644
--- a/boost/compute/algorithm/includes.hpp
+++ b/boost/compute/algorithm/includes.hpp
@@ -110,6 +110,7 @@ private:
/// \param last2 Iterator pointing to end of second set
/// \param queue Queue on which to execute
///
+/// Space complexity: \Omega(distance(\p first1, \p last1) + distance(\p first2, \p last2))
template<class InputIterator1, class InputIterator2>
inline bool includes(InputIterator1 first1,
InputIterator1 last1,
diff --git a/boost/compute/algorithm/inclusive_scan.hpp b/boost/compute/algorithm/inclusive_scan.hpp
index 9f98beaf7c..84f1b8cbf7 100644
--- a/boost/compute/algorithm/inclusive_scan.hpp
+++ b/boost/compute/algorithm/inclusive_scan.hpp
@@ -42,6 +42,10 @@ namespace compute {
///
/// \snippet test/test_scan.cpp inclusive_scan_int_multiplies
///
+/// Space complexity on GPUs: \Omega(n)<br>
+/// Space complexity on GPUs when \p first == \p result: \Omega(2n)<br>
+/// Space complexity on CPUs: \Omega(1)
+///
/// \see exclusive_scan()
template<class InputIterator, class OutputIterator, class BinaryOperator>
inline OutputIterator
diff --git a/boost/compute/algorithm/inner_product.hpp b/boost/compute/algorithm/inner_product.hpp
index 614611f91e..0aeaf9110e 100644
--- a/boost/compute/algorithm/inner_product.hpp
+++ b/boost/compute/algorithm/inner_product.hpp
@@ -26,6 +26,9 @@ namespace compute {
/// Returns the inner product of the elements in the range
/// [\p first1, \p last1) with the elements in the range beginning
/// at \p first2.
+///
+/// Space complexity: \Omega(1)<br>
+/// Space complexity when binary operator is recognized as associative: \Omega(n)
template<class InputIterator1, class InputIterator2, class T>
inline T inner_product(InputIterator1 first1,
InputIterator1 last1,
diff --git a/boost/compute/algorithm/inplace_merge.hpp b/boost/compute/algorithm/inplace_merge.hpp
index 3080950df5..91f5be5335 100644
--- a/boost/compute/algorithm/inplace_merge.hpp
+++ b/boost/compute/algorithm/inplace_merge.hpp
@@ -23,6 +23,8 @@ namespace compute {
/// Merges the sorted values in the range [\p first, \p middle) with
/// the sorted values in the range [\p middle, \p last) in-place.
+///
+/// Space complexity: \Omega(n)
template<class Iterator>
inline void inplace_merge(Iterator first,
Iterator middle,
diff --git a/boost/compute/algorithm/iota.hpp b/boost/compute/algorithm/iota.hpp
index 084c3d8d97..4cd7aa9c7b 100644
--- a/boost/compute/algorithm/iota.hpp
+++ b/boost/compute/algorithm/iota.hpp
@@ -26,6 +26,8 @@ namespace compute {
/// \snippet test/test_iota.cpp iota
///
/// Will fill \c vec with the values (\c 0, \c 1, \c 2, \c ...).
+///
+/// Space complexity: \Omega(1)
template<class BufferIterator, class T>
inline void iota(BufferIterator first,
BufferIterator last,
diff --git a/boost/compute/algorithm/is_partitioned.hpp b/boost/compute/algorithm/is_partitioned.hpp
index 3916825057..6ad24f240f 100644
--- a/boost/compute/algorithm/is_partitioned.hpp
+++ b/boost/compute/algorithm/is_partitioned.hpp
@@ -21,6 +21,8 @@ namespace compute {
/// Returns \c true if the values in the range [\p first, \p last)
/// are partitioned according to \p predicate.
+///
+/// Space complexity: \Omega(1)
template<class InputIterator, class UnaryPredicate>
inline bool is_partitioned(InputIterator first,
InputIterator last,
diff --git a/boost/compute/algorithm/is_permutation.hpp b/boost/compute/algorithm/is_permutation.hpp
index 1e502efb37..88b89b7973 100644
--- a/boost/compute/algorithm/is_permutation.hpp
+++ b/boost/compute/algorithm/is_permutation.hpp
@@ -36,6 +36,7 @@ namespace compute {
/// \param last2 Iterator pointing to end of second range
/// \param queue Queue on which to execute
///
+/// Space complexity: \Omega(distance(\p first1, \p last1) + distance(\p first2, \p last2))
template<class InputIterator1, class InputIterator2>
inline bool is_permutation(InputIterator1 first1,
InputIterator1 last1,
diff --git a/boost/compute/algorithm/is_sorted.hpp b/boost/compute/algorithm/is_sorted.hpp
index a605159ac3..7441620978 100644
--- a/boost/compute/algorithm/is_sorted.hpp
+++ b/boost/compute/algorithm/is_sorted.hpp
@@ -30,6 +30,8 @@ namespace compute {
///
/// \return \c true if the range [\p first, \p last) is sorted
///
+/// Space complexity: \Omega(1)
+///
/// \see sort()
template<class InputIterator, class Compare>
inline bool is_sorted(InputIterator first,
diff --git a/boost/compute/algorithm/lexicographical_compare.hpp b/boost/compute/algorithm/lexicographical_compare.hpp
index c4f7120807..952e678a68 100644
--- a/boost/compute/algorithm/lexicographical_compare.hpp
+++ b/boost/compute/algorithm/lexicographical_compare.hpp
@@ -42,10 +42,10 @@ const char lexicographical_compare_source[] =
template<class InputIterator1, class InputIterator2>
inline bool dispatch_lexicographical_compare(InputIterator1 first1,
- InputIterator1 last1,
- InputIterator2 first2,
- InputIterator2 last2,
- command_queue &queue)
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ command_queue &queue)
{
const boost::compute::context &context = queue.get_context();
@@ -103,6 +103,9 @@ inline bool dispatch_lexicographical_compare(InputIterator1 first1,
/// Checks if the first range [first1, last1) is lexicographically
/// less than the second range [first2, last2).
+///
+/// Space complexity:
+/// \Omega(max(distance(\p first1, \p last1), distance(\p first2, \p last2)))
template<class InputIterator1, class InputIterator2>
inline bool lexicographical_compare(InputIterator1 first1,
InputIterator1 last1,
diff --git a/boost/compute/algorithm/lower_bound.hpp b/boost/compute/algorithm/lower_bound.hpp
index b2011c66ef..f78bbd6364 100644
--- a/boost/compute/algorithm/lower_bound.hpp
+++ b/boost/compute/algorithm/lower_bound.hpp
@@ -22,6 +22,8 @@ namespace compute {
/// Returns an iterator pointing to the first element in the sorted
/// range [\p first, \p last) that is not less than \p value.
///
+/// Space complexity: \Omega(1)
+///
/// \see upper_bound()
template<class InputIterator, class T>
inline InputIterator
diff --git a/boost/compute/algorithm/max_element.hpp b/boost/compute/algorithm/max_element.hpp
index 55f2f7ffbf..f9df37420c 100644
--- a/boost/compute/algorithm/max_element.hpp
+++ b/boost/compute/algorithm/max_element.hpp
@@ -43,6 +43,9 @@ namespace compute {
/// boost::compute::max_element(data.begin(), data.end(), compare_first, queue);
/// \endcode
///
+/// Space complexity on CPUs: \Omega(1)<br>
+/// Space complexity on GPUs: \Omega(N)
+///
/// \see min_element()
template<class InputIterator, class Compare>
inline InputIterator
diff --git a/boost/compute/algorithm/merge.hpp b/boost/compute/algorithm/merge.hpp
index 875a283044..ff3e6e879a 100644
--- a/boost/compute/algorithm/merge.hpp
+++ b/boost/compute/algorithm/merge.hpp
@@ -37,6 +37,8 @@ namespace compute {
///
/// \return \c OutputIterator to the end of the result range
///
+/// Space complexity: \Omega(distance(\p first1, \p last1) + distance(\p first2, \p last2))
+///
/// \see inplace_merge()
template<class InputIterator1,
class InputIterator2,
diff --git a/boost/compute/algorithm/min_element.hpp b/boost/compute/algorithm/min_element.hpp
index 62744efb98..b52e2670cb 100644
--- a/boost/compute/algorithm/min_element.hpp
+++ b/boost/compute/algorithm/min_element.hpp
@@ -43,6 +43,9 @@ namespace compute {
/// boost::compute::min_element(data.begin(), data.end(), compare_first, queue);
/// \endcode
///
+/// Space complexity on CPUs: \Omega(1)<br>
+/// Space complexity on GPUs: \Omega(N)
+///
/// \see max_element()
template<class InputIterator, class Compare>
inline InputIterator
diff --git a/boost/compute/algorithm/minmax_element.hpp b/boost/compute/algorithm/minmax_element.hpp
index 3f44c09eaf..4b2aae6dee 100644
--- a/boost/compute/algorithm/minmax_element.hpp
+++ b/boost/compute/algorithm/minmax_element.hpp
@@ -31,6 +31,9 @@ namespace compute {
/// argument is less than (i.e. is ordered before) the second.
/// \param queue command queue to perform the operation
///
+/// Space complexity on CPUs: \Omega(1)<br>
+/// Space complexity on GPUs: \Omega(N)
+///
/// \see max_element(), min_element()
template<class InputIterator, class Compare>
inline std::pair<InputIterator, InputIterator>
diff --git a/boost/compute/algorithm/mismatch.hpp b/boost/compute/algorithm/mismatch.hpp
index e7db883004..ff31f49f97 100644
--- a/boost/compute/algorithm/mismatch.hpp
+++ b/boost/compute/algorithm/mismatch.hpp
@@ -28,6 +28,8 @@ namespace compute {
/// Returns a pair of iterators pointing to the first position where the
/// range [\p first1, \p last1) and the range starting at \p first2
/// differ.
+///
+/// Space complexity: \Omega(1)
template<class InputIterator1, class InputIterator2>
inline std::pair<InputIterator1, InputIterator2>
mismatch(InputIterator1 first1,
diff --git a/boost/compute/algorithm/next_permutation.hpp b/boost/compute/algorithm/next_permutation.hpp
index e81fbd2ee8..061ea1efe9 100644
--- a/boost/compute/algorithm/next_permutation.hpp
+++ b/boost/compute/algorithm/next_permutation.hpp
@@ -131,6 +131,7 @@ inline InputIterator np_ceiling(InputIterator first,
/// \param last Iterator pointing to end of range
/// \param queue Queue on which to execute
///
+/// Space complexity: \Omega(1)
template<class InputIterator>
inline bool next_permutation(InputIterator first,
InputIterator last,
diff --git a/boost/compute/algorithm/none_of.hpp b/boost/compute/algorithm/none_of.hpp
index c25dd12a87..fc3ed94bc1 100644
--- a/boost/compute/algorithm/none_of.hpp
+++ b/boost/compute/algorithm/none_of.hpp
@@ -20,6 +20,8 @@ namespace compute {
/// Returns \c true if \p predicate returns \c true for none of the elements in
/// the range [\p first, \p last).
///
+/// Space complexity: \Omega(1)
+///
/// \see all_of(), any_of()
template<class InputIterator, class UnaryPredicate>
inline bool none_of(InputIterator first,
diff --git a/boost/compute/algorithm/nth_element.hpp b/boost/compute/algorithm/nth_element.hpp
index 68f7a3dbc0..93344271dd 100644
--- a/boost/compute/algorithm/nth_element.hpp
+++ b/boost/compute/algorithm/nth_element.hpp
@@ -23,6 +23,8 @@ namespace compute {
/// Rearranges the elements in the range [\p first, \p last) such that
/// the \p nth element would be in that position in a sorted sequence.
+///
+/// Space complexity: \Omega(3n)
template<class Iterator, class Compare>
inline void nth_element(Iterator first,
Iterator nth,
diff --git a/boost/compute/algorithm/partial_sum.hpp b/boost/compute/algorithm/partial_sum.hpp
index d440369a5a..53d36a9db0 100644
--- a/boost/compute/algorithm/partial_sum.hpp
+++ b/boost/compute/algorithm/partial_sum.hpp
@@ -21,6 +21,10 @@ namespace compute {
/// Calculates the cumulative sum of the elements in the range [\p first,
/// \p last) and writes the resulting values to the range beginning at
/// \p result.
+///
+/// Space complexity on GPUs: \Omega(n)<br>
+/// Space complexity on GPUs when \p first == \p result: \Omega(2n)<br>
+/// Space complexity on CPUs: \Omega(1)
template<class InputIterator, class OutputIterator>
inline OutputIterator
partial_sum(InputIterator first,
diff --git a/boost/compute/algorithm/partition.hpp b/boost/compute/algorithm/partition.hpp
index 7860350e0d..59d0c78f7e 100644
--- a/boost/compute/algorithm/partition.hpp
+++ b/boost/compute/algorithm/partition.hpp
@@ -22,6 +22,8 @@ namespace compute {
/// Partitions the elements in the range [\p first, \p last) according to
/// \p predicate. Order of the elements need not be preserved.
///
+/// Space complexity: \Omega(3n)
+///
/// \see is_partitioned() and stable_partition()
///
template<class Iterator, class UnaryPredicate>
diff --git a/boost/compute/algorithm/partition_copy.hpp b/boost/compute/algorithm/partition_copy.hpp
index 80a2c6475f..3215ec0736 100644
--- a/boost/compute/algorithm/partition_copy.hpp
+++ b/boost/compute/algorithm/partition_copy.hpp
@@ -24,6 +24,8 @@ namespace compute {
/// and all of the elements for which \p predicate returns \c false to
/// the range beginning at \p first_false.
///
+/// Space complexity: \Omega(2n)
+///
/// \see partition()
template<class InputIterator,
class OutputIterator1,
diff --git a/boost/compute/algorithm/partition_point.hpp b/boost/compute/algorithm/partition_point.hpp
index 3cc2bc0ca6..748824512d 100644
--- a/boost/compute/algorithm/partition_point.hpp
+++ b/boost/compute/algorithm/partition_point.hpp
@@ -29,6 +29,8 @@ namespace compute {
/// \param predicate Unary predicate to be applied on each element
/// \param queue Queue on which to execute
///
+/// Space complexity: \Omega(1)
+///
/// \see partition() and stable_partition()
///
template<class InputIterator, class UnaryPredicate>
diff --git a/boost/compute/algorithm/prev_permutation.hpp b/boost/compute/algorithm/prev_permutation.hpp
index 03c01bf8f4..ea20835caa 100644
--- a/boost/compute/algorithm/prev_permutation.hpp
+++ b/boost/compute/algorithm/prev_permutation.hpp
@@ -131,6 +131,7 @@ inline InputIterator pp_floor(InputIterator first,
/// \param last Iterator pointing to end of range
/// \param queue Queue on which to execute
///
+/// Space complexity: \Omega(1)
template<class InputIterator>
inline bool prev_permutation(InputIterator first,
InputIterator last,
diff --git a/boost/compute/algorithm/random_shuffle.hpp b/boost/compute/algorithm/random_shuffle.hpp
index 7d2d46a133..8e020830a5 100644
--- a/boost/compute/algorithm/random_shuffle.hpp
+++ b/boost/compute/algorithm/random_shuffle.hpp
@@ -28,6 +28,8 @@ namespace compute {
/// Randomly shuffles the elements in the range [\p first, \p last).
///
+/// Space complexity: \Omega(2n)
+///
/// \see scatter()
template<class Iterator>
inline void random_shuffle(Iterator first,
diff --git a/boost/compute/algorithm/reduce.hpp b/boost/compute/algorithm/reduce.hpp
index 19d070019f..e71d90fe24 100644
--- a/boost/compute/algorithm/reduce.hpp
+++ b/boost/compute/algorithm/reduce.hpp
@@ -153,6 +153,7 @@ block_reduce(InputIterator first,
return result_vector;
}
+// Space complexity: O( ceil(n / 2 / 256) )
template<class InputIterator, class OutputIterator, class BinaryFunction>
inline void generic_reduce(InputIterator first,
InputIterator last,
@@ -264,6 +265,9 @@ inline void dispatch_reduce(InputIterator first,
/// efficient on parallel hardware. For more information, see the documentation
/// on the \c accumulate() algorithm.
///
+/// Space complexity on GPUs: \Omega(n)<br>
+/// Space complexity on CPUs: \Omega(1)
+///
/// \see accumulate()
template<class InputIterator, class OutputIterator, class BinaryFunction>
inline void reduce(InputIterator first,
diff --git a/boost/compute/algorithm/reduce_by_key.hpp b/boost/compute/algorithm/reduce_by_key.hpp
index 87c73e887f..1a233c7dd4 100644
--- a/boost/compute/algorithm/reduce_by_key.hpp
+++ b/boost/compute/algorithm/reduce_by_key.hpp
@@ -51,6 +51,9 @@ namespace compute {
///
/// \snippet test/test_reduce_by_key.cpp reduce_by_key_int
///
+/// Space complexity on GPUs: \Omega(2n)<br>
+/// Space complexity on CPUs: \Omega(1)
+///
/// \see reduce()
template<class InputKeyIterator, class InputValueIterator,
class OutputKeyIterator, class OutputValueIterator,
diff --git a/boost/compute/algorithm/remove.hpp b/boost/compute/algorithm/remove.hpp
index 98feb1f9d8..086ba8cc7f 100644
--- a/boost/compute/algorithm/remove.hpp
+++ b/boost/compute/algorithm/remove.hpp
@@ -22,6 +22,8 @@ namespace compute {
/// Removes each element equal to \p value in the range [\p first,
/// \p last).
///
+/// Space complexity: \Omega(3n)
+///
/// \see remove_if()
template<class Iterator, class T>
inline Iterator remove(Iterator first,
diff --git a/boost/compute/algorithm/remove_if.hpp b/boost/compute/algorithm/remove_if.hpp
index 5e416bef88..9aece18bbd 100644
--- a/boost/compute/algorithm/remove_if.hpp
+++ b/boost/compute/algorithm/remove_if.hpp
@@ -22,6 +22,8 @@ namespace compute {
/// Removes each element for which \p predicate returns \c true in the
/// range [\p first, \p last).
///
+/// Space complexity: \Omega(3n)
+///
/// \see remove()
template<class Iterator, class Predicate>
inline Iterator remove_if(Iterator first,
diff --git a/boost/compute/algorithm/replace.hpp b/boost/compute/algorithm/replace.hpp
index fd649a2fad..336c1d3e0f 100644
--- a/boost/compute/algorithm/replace.hpp
+++ b/boost/compute/algorithm/replace.hpp
@@ -68,6 +68,8 @@ private:
/// Replaces each instance of \p old_value in the range [\p first,
/// \p last) with \p new_value.
+///
+/// Space complexity: \Omega(1)
template<class Iterator, class T>
inline void replace(Iterator first,
Iterator last,
diff --git a/boost/compute/algorithm/replace_copy.hpp b/boost/compute/algorithm/replace_copy.hpp
index 7224bd3ae6..34f61b514f 100644
--- a/boost/compute/algorithm/replace_copy.hpp
+++ b/boost/compute/algorithm/replace_copy.hpp
@@ -25,6 +25,8 @@ namespace compute {
/// beginning at \p result while replacing each instance of \p old_value
/// with \p new_value.
///
+/// Space complexity: \Omega(1)
+///
/// \see replace()
template<class InputIterator, class OutputIterator, class T>
inline OutputIterator
diff --git a/boost/compute/algorithm/reverse.hpp b/boost/compute/algorithm/reverse.hpp
index b6a9e8098c..15fe5533ac 100644
--- a/boost/compute/algorithm/reverse.hpp
+++ b/boost/compute/algorithm/reverse.hpp
@@ -52,6 +52,8 @@ struct reverse_kernel : public meta_kernel
/// Reverses the elements in the range [\p first, \p last).
///
+/// Space complexity: \Omega(1)
+///
/// \see reverse_copy()
template<class Iterator>
inline void reverse(Iterator first,
diff --git a/boost/compute/algorithm/reverse_copy.hpp b/boost/compute/algorithm/reverse_copy.hpp
index c839f44651..9fda9d4e27 100644
--- a/boost/compute/algorithm/reverse_copy.hpp
+++ b/boost/compute/algorithm/reverse_copy.hpp
@@ -51,6 +51,8 @@ struct reverse_copy_kernel : public meta_kernel
/// Copies the elements in the range [\p first, \p last) in reversed
/// order to the range beginning at \p result.
///
+/// Space complexity: \Omega(1)
+///
/// \see reverse()
template<class InputIterator, class OutputIterator>
inline OutputIterator
diff --git a/boost/compute/algorithm/rotate.hpp b/boost/compute/algorithm/rotate.hpp
index 54cb073cc2..715699340d 100644
--- a/boost/compute/algorithm/rotate.hpp
+++ b/boost/compute/algorithm/rotate.hpp
@@ -21,6 +21,8 @@ namespace compute {
/// Performs left rotation such that element at \p n_first comes to the
/// beginning.
///
+/// Space complexity: \Omega(distance(\p first, \p last))
+///
/// \see rotate_copy()
template<class InputIterator>
inline void rotate(InputIterator first,
diff --git a/boost/compute/algorithm/rotate_copy.hpp b/boost/compute/algorithm/rotate_copy.hpp
index fa1b44c5e5..679b3c998b 100644
--- a/boost/compute/algorithm/rotate_copy.hpp
+++ b/boost/compute/algorithm/rotate_copy.hpp
@@ -20,6 +20,8 @@ namespace compute {
/// Performs left rotation such that element at n_first comes to the
/// beginning and the output is stored in range starting at result.
///
+/// Space complexity: \Omega(1)
+///
/// \see rotate()
template<class InputIterator, class OutputIterator>
inline void rotate_copy(InputIterator first,
diff --git a/boost/compute/algorithm/scatter.hpp b/boost/compute/algorithm/scatter.hpp
index bea4201628..8ae5a99443 100644
--- a/boost/compute/algorithm/scatter.hpp
+++ b/boost/compute/algorithm/scatter.hpp
@@ -79,6 +79,8 @@ private:
/// beginning at \p result using the output indices from the range beginning
/// at \p map.
///
+/// Space complexity: \Omega(1)
+///
/// \see gather()
template<class InputIterator, class MapIterator, class OutputIterator>
inline void scatter(InputIterator first,
diff --git a/boost/compute/algorithm/scatter_if.hpp b/boost/compute/algorithm/scatter_if.hpp
index 159edd8c86..c7db51d3be 100644
--- a/boost/compute/algorithm/scatter_if.hpp
+++ b/boost/compute/algorithm/scatter_if.hpp
@@ -83,7 +83,7 @@ private:
/// at \p map if stencil is resolved to true. By default the predicate is
/// an identity
///
-///
+/// Space complexity: \Omega(1)
template<class InputIterator, class MapIterator, class StencilIterator, class OutputIterator,
class Predicate>
inline void scatter_if(InputIterator first,
diff --git a/boost/compute/algorithm/search.hpp b/boost/compute/algorithm/search.hpp
index 3d3d035b3c..a1f3dece62 100644
--- a/boost/compute/algorithm/search.hpp
+++ b/boost/compute/algorithm/search.hpp
@@ -34,6 +34,7 @@ namespace compute {
/// \param p_last Iterator pointing to end of pattern
/// \param queue Queue on which to execute
///
+/// Space complexity: \Omega(distance(\p t_first, \p t_last))
template<class TextIterator, class PatternIterator>
inline TextIterator search(TextIterator t_first,
TextIterator t_last,
diff --git a/boost/compute/algorithm/search_n.hpp b/boost/compute/algorithm/search_n.hpp
index 9e03111bb0..86ff64dfd9 100644
--- a/boost/compute/algorithm/search_n.hpp
+++ b/boost/compute/algorithm/search_n.hpp
@@ -102,6 +102,7 @@ private:
/// \param value Value which repeats
/// \param queue Queue on which to execute
///
+/// Space complexity: \Omega(distance(\p t_first, \p t_last))
template<class TextIterator, class ValueType>
inline TextIterator search_n(TextIterator t_first,
TextIterator t_last,
diff --git a/boost/compute/algorithm/set_difference.hpp b/boost/compute/algorithm/set_difference.hpp
index 17ce7bd3f6..85a846ba13 100644
--- a/boost/compute/algorithm/set_difference.hpp
+++ b/boost/compute/algorithm/set_difference.hpp
@@ -122,6 +122,8 @@ private:
/// will be stored
/// \param queue Queue on which to execute
///
+/// Space complexity:
+/// \Omega(2(distance(\p first1, \p last1) + distance(\p first2, \p last2)))
template<class InputIterator1, class InputIterator2, class OutputIterator>
inline OutputIterator set_difference(InputIterator1 first1,
InputIterator1 last1,
diff --git a/boost/compute/algorithm/set_intersection.hpp b/boost/compute/algorithm/set_intersection.hpp
index 50f291e84a..74d46f57c6 100644
--- a/boost/compute/algorithm/set_intersection.hpp
+++ b/boost/compute/algorithm/set_intersection.hpp
@@ -110,6 +110,8 @@ private:
/// will be stored
/// \param queue Queue on which to execute
///
+/// Space complexity:
+/// \Omega(2(distance(\p first1, \p last1) + distance(\p first2, \p last2)))
template<class InputIterator1, class InputIterator2, class OutputIterator>
inline OutputIterator set_intersection(InputIterator1 first1,
InputIterator1 last1,
diff --git a/boost/compute/algorithm/set_symmetric_difference.hpp b/boost/compute/algorithm/set_symmetric_difference.hpp
index 6e60b38511..34d280daa3 100644
--- a/boost/compute/algorithm/set_symmetric_difference.hpp
+++ b/boost/compute/algorithm/set_symmetric_difference.hpp
@@ -133,13 +133,16 @@ private:
/// difference will be stored
/// \param queue Queue on which to execute
///
+/// Space complexity:
+/// \Omega(2(distance(\p first1, \p last1) + distance(\p first2, \p last2)))
template<class InputIterator1, class InputIterator2, class OutputIterator>
-inline OutputIterator set_symmetric_difference(InputIterator1 first1,
- InputIterator1 last1,
- InputIterator2 first2,
- InputIterator2 last2,
- OutputIterator result,
- command_queue &queue = system::default_queue())
+inline OutputIterator
+set_symmetric_difference(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator result,
+ command_queue &queue = system::default_queue())
{
typedef typename std::iterator_traits<InputIterator1>::value_type value_type;
diff --git a/boost/compute/algorithm/set_union.hpp b/boost/compute/algorithm/set_union.hpp
index c61f7b29b3..6b405a0905 100644
--- a/boost/compute/algorithm/set_union.hpp
+++ b/boost/compute/algorithm/set_union.hpp
@@ -135,6 +135,8 @@ private:
/// will be stored
/// \param queue Queue on which to execute
///
+/// Space complexity:
+/// \Omega(2(distance(\p first1, \p last1) + distance(\p first2, \p last2)))
template<class InputIterator1, class InputIterator2, class OutputIterator>
inline OutputIterator set_union(InputIterator1 first1,
InputIterator1 last1,
diff --git a/boost/compute/algorithm/sort.hpp b/boost/compute/algorithm/sort.hpp
index 7e0a583e3e..b8fa90f335 100644
--- a/boost/compute/algorithm/sort.hpp
+++ b/boost/compute/algorithm/sort.hpp
@@ -176,6 +176,8 @@ inline void dispatch_sort(Iterator first,
/// boost::compute::sort(data.begin(), data.end(), queue);
/// \endcode
///
+/// Space complexity: \Omega(n)
+///
/// \see is_sorted()
template<class Iterator, class Compare>
inline void sort(Iterator first,
diff --git a/boost/compute/algorithm/sort_by_key.hpp b/boost/compute/algorithm/sort_by_key.hpp
index c39bcf9890..fdd2d1c481 100644
--- a/boost/compute/algorithm/sort_by_key.hpp
+++ b/boost/compute/algorithm/sort_by_key.hpp
@@ -128,6 +128,8 @@ inline void dispatch_sort_by_key(KeyIterator keys_first,
///
/// If no compare function is specified, \c less is used.
///
+/// Space complexity: \Omega(2n)
+///
/// \see sort()
template<class KeyIterator, class ValueIterator, class Compare>
inline void sort_by_key(KeyIterator keys_first,
diff --git a/boost/compute/algorithm/stable_partition.hpp b/boost/compute/algorithm/stable_partition.hpp
index 283b068283..2b07f034b9 100644
--- a/boost/compute/algorithm/stable_partition.hpp
+++ b/boost/compute/algorithm/stable_partition.hpp
@@ -33,6 +33,8 @@ namespace compute {
/// \param predicate Unary predicate to be applied on each element
/// \param queue Queue on which to execute
///
+/// Space complexity: \Omega(3n)
+///
/// \see is_partitioned() and partition()
///
template<class Iterator, class UnaryPredicate>
diff --git a/boost/compute/algorithm/stable_sort.hpp b/boost/compute/algorithm/stable_sort.hpp
index 381fc81bc0..0857d75dc9 100644
--- a/boost/compute/algorithm/stable_sort.hpp
+++ b/boost/compute/algorithm/stable_sort.hpp
@@ -72,6 +72,8 @@ dispatch_gpu_stable_sort(buffer_iterator<T> first,
/// Sorts the values in the range [\p first, \p last) according to
/// \p compare. The relative order of identical values is preserved.
///
+/// Space complexity: \Omega(n)
+///
/// \see sort(), is_sorted()
template<class Iterator, class Compare>
inline void stable_sort(Iterator first,
diff --git a/boost/compute/algorithm/stable_sort_by_key.hpp b/boost/compute/algorithm/stable_sort_by_key.hpp
index 878f999f44..ce8811ef19 100644
--- a/boost/compute/algorithm/stable_sort_by_key.hpp
+++ b/boost/compute/algorithm/stable_sort_by_key.hpp
@@ -126,6 +126,8 @@ inline void dispatch_ssort_by_key(KeyIterator keys_first,
///
/// If no compare function is specified, \c less is used.
///
+/// Space complexity: \Omega(2n)
+///
/// \see sort()
template<class KeyIterator, class ValueIterator, class Compare>
inline void stable_sort_by_key(KeyIterator keys_first,
diff --git a/boost/compute/algorithm/swap_ranges.hpp b/boost/compute/algorithm/swap_ranges.hpp
index 6ff3e14f6a..a706df7a61 100644
--- a/boost/compute/algorithm/swap_ranges.hpp
+++ b/boost/compute/algorithm/swap_ranges.hpp
@@ -21,6 +21,8 @@ namespace compute {
/// Swaps the elements in the range [\p first1, \p last1) with the
/// elements in the range beginning at \p first2.
+///
+/// Space complexity: \Omega(distance(\p first1, \p last1))
template<class Iterator1, class Iterator2>
inline Iterator2 swap_ranges(Iterator1 first1,
Iterator1 last1,
diff --git a/boost/compute/algorithm/transform.hpp b/boost/compute/algorithm/transform.hpp
index 68750a6523..9137604d55 100644
--- a/boost/compute/algorithm/transform.hpp
+++ b/boost/compute/algorithm/transform.hpp
@@ -29,6 +29,8 @@ namespace compute {
///
/// \snippet test/test_transform.cpp transform_abs
///
+/// Space complexity: \Omega(1)
+///
/// \see copy()
template<class InputIterator, class OutputIterator, class UnaryOperator>
inline OutputIterator transform(InputIterator first,
diff --git a/boost/compute/algorithm/transform_if.hpp b/boost/compute/algorithm/transform_if.hpp
index 0eb0fd434e..9a98102d27 100644
--- a/boost/compute/algorithm/transform_if.hpp
+++ b/boost/compute/algorithm/transform_if.hpp
@@ -26,6 +26,7 @@ namespace boost {
namespace compute {
namespace detail {
+// Space complexity: O(2n)
template<class InputIterator, class OutputIterator, class UnaryFunction, class Predicate>
inline OutputIterator transform_if_impl(InputIterator first,
InputIterator last,
@@ -53,14 +54,12 @@ inline OutputIterator transform_if_impl(InputIterator first,
<< predicate(first[k1.get_global_id(0)]) << " ? 1 : 0;\n";
k1.exec_1d(queue, 0, count);
- // count number of elements to be copied
- size_t copied_element_count =
- ::boost::compute::count(indices.begin(), indices.end(), 1, queue);
-
// scan indices
+ size_t copied_element_count = (indices.cend() - 1).read(queue);
::boost::compute::exclusive_scan(
indices.begin(), indices.end(), indices.begin(), queue
);
+ copied_element_count += (indices.cend() - 1).read(queue); // last scan element plus last mask element
// copy values
::boost::compute::detail::meta_kernel k2("transform_if_do_copy");
@@ -98,6 +97,8 @@ inline discard_iterator transform_if_impl(InputIterator first,
/// Copies each element in the range [\p first, \p last) for which
/// \p predicate returns \c true to the range beginning at \p result.
+///
+/// Space complexity: O(2n)
template<class InputIterator, class OutputIterator, class UnaryFunction, class Predicate>
inline OutputIterator transform_if(InputIterator first,
InputIterator last,
diff --git a/boost/compute/algorithm/transform_reduce.hpp b/boost/compute/algorithm/transform_reduce.hpp
index fbeee5a691..a59a76aefd 100644
--- a/boost/compute/algorithm/transform_reduce.hpp
+++ b/boost/compute/algorithm/transform_reduce.hpp
@@ -30,6 +30,9 @@ namespace compute {
///
/// \snippet test/test_transform_reduce.cpp sum_abs_int
///
+/// Space complexity on GPUs: \Omega(n)<br>
+/// Space complexity on CPUs: \Omega(1)
+///
/// \see reduce(), inner_product()
template<class InputIterator,
class OutputIterator,
diff --git a/boost/compute/algorithm/unique.hpp b/boost/compute/algorithm/unique.hpp
index faa36bad9d..8b7e2a0d0d 100644
--- a/boost/compute/algorithm/unique.hpp
+++ b/boost/compute/algorithm/unique.hpp
@@ -31,6 +31,8 @@ namespace compute {
///
/// \return \c InputIterator to the new logical end of the range
///
+/// Space complexity: \Omega(4n)
+///
/// \see unique_copy()
template<class InputIterator, class BinaryPredicate>
inline InputIterator unique(InputIterator first,
diff --git a/boost/compute/algorithm/unique_copy.hpp b/boost/compute/algorithm/unique_copy.hpp
index 2ce60a9359..d5fffd4ff9 100644
--- a/boost/compute/algorithm/unique_copy.hpp
+++ b/boost/compute/algorithm/unique_copy.hpp
@@ -127,6 +127,8 @@ inline OutputIterator unique_copy(InputIterator first,
///
/// \return \c OutputIterator to the end of the result range
///
+/// Space complexity: \Omega(4n)
+///
/// \see unique()
template<class InputIterator, class OutputIterator, class BinaryPredicate>
inline OutputIterator unique_copy(InputIterator first,
diff --git a/boost/compute/algorithm/upper_bound.hpp b/boost/compute/algorithm/upper_bound.hpp
index a5a82d301c..f592c79b9a 100644
--- a/boost/compute/algorithm/upper_bound.hpp
+++ b/boost/compute/algorithm/upper_bound.hpp
@@ -22,6 +22,8 @@ namespace compute {
/// Returns an iterator pointing to the first element in the sorted
/// range [\p first, \p last) that is not less than or equal to
/// \p value.
+///
+/// Space complexity: \Omega(1)
template<class InputIterator, class T>
inline InputIterator
upper_bound(InputIterator first,
diff --git a/boost/compute/buffer.hpp b/boost/compute/buffer.hpp
index b5a48806d5..128403cd62 100644
--- a/boost/compute/buffer.hpp
+++ b/boost/compute/buffer.hpp
@@ -154,7 +154,7 @@ public:
/// \p queue to perform the copy.
buffer clone(command_queue &queue) const;
- #if defined(CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ #if defined(BOOST_COMPUTE_CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
/// Creates a new buffer out of this buffer.
/// The new buffer is a sub region of this buffer.
/// \p flags The mem_flags which should be used to create the new buffer
@@ -187,7 +187,7 @@ public:
return buffer(mem, false);
}
- #endif // CL_VERSION_1_1
+ #endif // BOOST_COMPUTE_CL_VERSION_1_1
};
/// \internal_ define get_info() specializations for buffer
@@ -201,12 +201,12 @@ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(buffer,
((cl_context, CL_MEM_CONTEXT))
)
-#ifdef CL_VERSION_1_1
+#ifdef BOOST_COMPUTE_CL_VERSION_1_1
BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(buffer,
((cl_mem, CL_MEM_ASSOCIATED_MEMOBJECT))
((size_t, CL_MEM_OFFSET))
)
-#endif // CL_VERSION_1_1
+#endif // BOOST_COMPUTE_CL_VERSION_1_1
namespace detail {
diff --git a/boost/compute/cl.hpp b/boost/compute/cl.hpp
index c439d8dfdc..fe25ffde56 100644
--- a/boost/compute/cl.hpp
+++ b/boost/compute/cl.hpp
@@ -11,10 +11,58 @@
#ifndef BOOST_COMPUTE_CL_HPP
#define BOOST_COMPUTE_CL_HPP
+#if defined(BOOST_COMPUTE_MAX_CL_VERSION)
+# if !defined(CL_USE_DEPRECATED_OPENCL_2_1_APIS) && BOOST_COMPUTE_MAX_CL_VERSION < 202
+# define CL_USE_DEPRECATED_OPENCL_2_1_APIS
+# endif
+# if !defined(CL_USE_DEPRECATED_OPENCL_2_0_APIS) && BOOST_COMPUTE_MAX_CL_VERSION < 201
+# define CL_USE_DEPRECATED_OPENCL_2_0_APIS
+# endif
+# if !defined(CL_USE_DEPRECATED_OPENCL_1_2_APIS) && BOOST_COMPUTE_MAX_CL_VERSION < 200
+# define CL_USE_DEPRECATED_OPENCL_1_2_APIS
+# endif
+# if !defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) && BOOST_COMPUTE_MAX_CL_VERSION < 102
+# define CL_USE_DEPRECATED_OPENCL_1_1_APIS
+# endif
+# if !defined(CL_USE_DEPRECATED_OPENCL_1_0_APIS) && BOOST_COMPUTE_MAX_CL_VERSION < 101
+# define CL_USE_DEPRECATED_OPENCL_1_0_APIS
+# endif
+#endif
+
#if defined(__APPLE__)
#include <OpenCL/cl.h>
#else
#include <CL/cl.h>
#endif
+// select what OpenCL core API versions to use
+#if defined(CL_VERSION_1_0)
+# define BOOST_COMPUTE_CL_VERSION_1_0
+#endif
+#if defined(CL_VERSION_1_1)
+# if !defined(BOOST_COMPUTE_MAX_CL_VERSION) || BOOST_COMPUTE_MAX_CL_VERSION >= 101
+# define BOOST_COMPUTE_CL_VERSION_1_1
+# endif
+#endif
+#if defined(CL_VERSION_1_2)
+# if !defined(BOOST_COMPUTE_MAX_CL_VERSION) || BOOST_COMPUTE_MAX_CL_VERSION >= 102
+# define BOOST_COMPUTE_CL_VERSION_1_2
+# endif
+#endif
+#if defined(CL_VERSION_2_0)
+# if !defined(BOOST_COMPUTE_MAX_CL_VERSION) || BOOST_COMPUTE_MAX_CL_VERSION >= 200
+# define BOOST_COMPUTE_CL_VERSION_2_0
+# endif
+#endif
+#if defined(CL_VERSION_2_1)
+# if !defined(BOOST_COMPUTE_MAX_CL_VERSION) || BOOST_COMPUTE_MAX_CL_VERSION >= 201
+# define BOOST_COMPUTE_CL_VERSION_2_1
+# endif
+#endif
+#if defined(CL_VERSION_2_2)
+# if !defined(BOOST_COMPUTE_MAX_CL_VERSION) || BOOST_COMPUTE_MAX_CL_VERSION >= 202
+# define BOOST_COMPUTE_CL_VERSION_2_2
+# endif
+#endif
+
#endif // BOOST_COMPUTE_CL_HPP
diff --git a/boost/compute/command_queue.hpp b/boost/compute/command_queue.hpp
index 2a1328a959..d9e81e0bd4 100644
--- a/boost/compute/command_queue.hpp
+++ b/boost/compute/command_queue.hpp
@@ -81,12 +81,17 @@ public:
enum properties {
enable_profiling = CL_QUEUE_PROFILING_ENABLE,
enable_out_of_order_execution = CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE
+ #ifdef BOOST_COMPUTE_CL_VERSION_2_0
+ ,
+ on_device = CL_QUEUE_ON_DEVICE,
+ on_device_default = CL_QUEUE_ON_DEVICE_DEFAULT
+ #endif
};
enum map_flags {
map_read = CL_MAP_READ,
map_write = CL_MAP_WRITE
- #ifdef CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
,
map_write_invalidate_region = CL_MAP_WRITE_INVALIDATE_REGION
#endif
@@ -118,7 +123,7 @@ public:
cl_int error = 0;
- #ifdef CL_VERSION_2_0
+ #ifdef BOOST_COMPUTE_CL_VERSION_2_0
if (device.check_version(2, 0)){
std::vector<cl_queue_properties> queue_properties;
if(properties){
@@ -323,7 +328,7 @@ public:
return event_;
}
- #if defined(CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ #if defined(BOOST_COMPUTE_CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
/// Enqueues a command to read a rectangular region from \p buffer to
/// host memory.
///
@@ -417,7 +422,7 @@ public:
return event_;
}
- #endif // CL_VERSION_1_1
+ #endif // BOOST_COMPUTE_CL_VERSION_1_1
/// Enqueues a command to write data from host memory to \p buffer.
///
@@ -494,7 +499,7 @@ public:
return event_;
}
- #if defined(CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ #if defined(BOOST_COMPUTE_CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
/// Enqueues a command to write a rectangular region from host memory
/// to \p buffer.
///
@@ -588,7 +593,7 @@ public:
return event_;
}
- #endif // CL_VERSION_1_1
+ #endif // BOOST_COMPUTE_CL_VERSION_1_1
/// Enqueues a command to copy data from \p src_buffer to
/// \p dst_buffer.
@@ -630,7 +635,7 @@ public:
return event_;
}
- #if defined(CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ #if defined(BOOST_COMPUTE_CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
/// Enqueues a command to copy a rectangular region from
/// \p src_buffer to \p dst_buffer.
///
@@ -676,9 +681,9 @@ public:
return event_;
}
- #endif // CL_VERSION_1_1
+ #endif // BOOST_COMPUTE_CL_VERSION_1_1
- #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ #if defined(BOOST_COMPUTE_CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
/// Enqueues a command to fill \p buffer with \p pattern.
///
/// \see_opencl_ref{clEnqueueFillBuffer}
@@ -717,7 +722,7 @@ public:
return event_;
}
- #endif // CL_VERSION_1_2
+ #endif // BOOST_COMPUTE_CL_VERSION_1_2
/// Enqueues a command to map \p buffer into the host address space.
/// Event associated with map operation is returned through
@@ -1269,7 +1274,7 @@ public:
return event_;
}
- #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ #if defined(BOOST_COMPUTE_CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
/// Enqueues a command to fill \p image with \p fill_color.
///
/// \see_opencl_ref{clEnqueueFillImage}
@@ -1354,7 +1359,7 @@ public:
return event_;
}
- #endif // CL_VERSION_1_2
+ #endif // BOOST_COMPUTE_CL_VERSION_1_2
/// Enqueues a kernel for execution.
///
@@ -1438,7 +1443,7 @@ public:
// clEnqueueTask() was deprecated in OpenCL 2.0. In that case we
// just forward to the equivalent clEnqueueNDRangeKernel() call.
- #ifdef CL_VERSION_2_0
+ #ifdef BOOST_COMPUTE_CL_VERSION_2_0
size_t one = 1;
cl_int ret = clEnqueueNDRangeKernel(
m_queue, kernel, 1, 0, &one, &one,
@@ -1511,7 +1516,10 @@ public:
{
BOOST_ASSERT(m_queue != 0);
- clFlush(m_queue);
+ cl_int ret = clFlush(m_queue);
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
}
/// Blocks until all outstanding commands in the queue have finished.
@@ -1521,7 +1529,10 @@ public:
{
BOOST_ASSERT(m_queue != 0);
- clFinish(m_queue);
+ cl_int ret = clFinish(m_queue);
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
}
/// Enqueues a barrier in the queue.
@@ -1530,11 +1541,11 @@ public:
BOOST_ASSERT(m_queue != 0);
cl_int ret = CL_SUCCESS;
- #ifdef CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
if(get_device().check_version(1, 2)){
ret = clEnqueueBarrierWithWaitList(m_queue, 0, 0, 0);
} else
- #endif // CL_VERSION_1_2
+ #endif // BOOST_COMPUTE_CL_VERSION_1_2
{
// Suppress deprecated declarations warning
BOOST_COMPUTE_DISABLE_DEPRECATED_DECLARATIONS();
@@ -1547,7 +1558,7 @@ public:
}
}
- #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ #if defined(BOOST_COMPUTE_CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
/// Enqueues a barrier in the queue after \p events.
///
/// \opencl_version_warning{1,2}
@@ -1568,7 +1579,7 @@ public:
return event_;
}
- #endif // CL_VERSION_1_2
+ #endif // BOOST_COMPUTE_CL_VERSION_1_2
/// Enqueues a marker in the queue and returns an event that can be
/// used to track its progress.
@@ -1577,7 +1588,7 @@ public:
event event_;
cl_int ret = CL_SUCCESS;
- #ifdef CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
if(get_device().check_version(1, 2)){
ret = clEnqueueMarkerWithWaitList(m_queue, 0, 0, &event_.get());
} else
@@ -1596,7 +1607,7 @@ public:
return event_;
}
- #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ #if defined(BOOST_COMPUTE_CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
/// Enqueues a marker after \p events in the queue and returns an
/// event that can be used to track its progress.
///
@@ -1615,9 +1626,9 @@ public:
return event_;
}
- #endif // CL_VERSION_1_2
+ #endif // BOOST_COMPUTE_CL_VERSION_1_2
- #if defined(CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ #if defined(BOOST_COMPUTE_CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
/// Enqueues a command to copy \p size bytes of data from \p src_ptr to
/// \p dst_ptr.
///
@@ -1797,7 +1808,7 @@ public:
return event_;
}
- #endif // CL_VERSION_2_0
+ #endif // BOOST_COMPUTE_CL_VERSION_2_0
/// Returns \c true if the command queue is the same at \p other.
bool operator==(const command_queue &other) const
diff --git a/boost/compute/container/detail/scalar.hpp b/boost/compute/container/detail/scalar.hpp
index 7ecd86e540..4dee76d2b4 100644
--- a/boost/compute/container/detail/scalar.hpp
+++ b/boost/compute/container/detail/scalar.hpp
@@ -12,6 +12,7 @@
#define BOOST_COMPUTE_CONTAINER_DETAIL_SCALAR_HPP
#include <boost/compute/buffer.hpp>
+#include <boost/compute/event.hpp>
#include <boost/compute/detail/read_write_single_value.hpp>
namespace boost {
@@ -40,9 +41,9 @@ public:
return read_single_value<T>(m_buffer, 0, queue);
}
- void write(const T &value, command_queue &queue)
+ event write(const T &value, command_queue &queue)
{
- write_single_value<T>(value, m_buffer, 0, queue);
+ return write_single_value<T>(value, m_buffer, 0, queue);
}
const buffer& get_buffer() const
diff --git a/boost/compute/container/valarray.hpp b/boost/compute/container/valarray.hpp
index 8ac8e01753..981ec2e545 100644
--- a/boost/compute/container/valarray.hpp
+++ b/boost/compute/container/valarray.hpp
@@ -67,6 +67,7 @@ public:
valarray(const valarray<T> &other)
: m_buffer(other.m_buffer.get_context(), other.size() * sizeof(T))
{
+ copy(other.begin(), other.end(), begin());
}
valarray(const std::valarray<T> &valarray,
diff --git a/boost/compute/context.hpp b/boost/compute/context.hpp
index 61e84e9767..13154a968a 100644
--- a/boost/compute/context.hpp
+++ b/boost/compute/context.hpp
@@ -233,11 +233,11 @@ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(context,
((std::vector<cl_context_properties>, CL_CONTEXT_PROPERTIES))
)
-#ifdef CL_VERSION_1_1
+#ifdef BOOST_COMPUTE_CL_VERSION_1_1
BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(context,
((cl_uint, CL_CONTEXT_NUM_DEVICES))
)
-#endif // CL_VERSION_1_1
+#endif // BOOST_COMPUTE_CL_VERSION_1_1
} // end compute namespace
} // end boost namespace
diff --git a/boost/compute/detail/buffer_value.hpp b/boost/compute/detail/buffer_value.hpp
index 6a4e78fc19..478fc03252 100644
--- a/boost/compute/detail/buffer_value.hpp
+++ b/boost/compute/detail/buffer_value.hpp
@@ -124,7 +124,9 @@ public:
const context &context = m_buffer.get_context();
command_queue queue(context, context.get_device());
- detail::write_single_value<T>(value, m_buffer, m_index / sizeof(T), queue);
+ detail::write_single_value<T>(
+ value, m_buffer, m_index / sizeof(T), queue
+ ).wait();
return *this;
}
diff --git a/boost/compute/detail/duration.hpp b/boost/compute/detail/duration.hpp
index 601f12d291..98e825fb3c 100644
--- a/boost/compute/detail/duration.hpp
+++ b/boost/compute/detail/duration.hpp
@@ -17,7 +17,9 @@
#include <chrono>
#endif
+#ifndef BOOST_COMPUTE_NO_BOOST_CHRONO
#include <boost/chrono/duration.hpp>
+#endif
namespace boost {
namespace compute {
@@ -34,6 +36,7 @@ make_duration_from_nanoseconds(std::chrono::duration<Rep, Period>, size_t nanose
}
#endif // BOOST_COMPUTE_NO_HDR_CHRONO
+#ifndef BOOST_COMPUTE_NO_BOOST_CHRONO
template<class Rep, class Period>
inline boost::chrono::duration<Rep, Period>
make_duration_from_nanoseconds(boost::chrono::duration<Rep, Period>, size_t nanoseconds)
@@ -42,6 +45,7 @@ make_duration_from_nanoseconds(boost::chrono::duration<Rep, Period>, size_t nano
boost::chrono::nanoseconds(nanoseconds)
);
}
+#endif // BOOST_COMPUTE_NO_BOOST_CHRONO
} // end detail namespace
} // end compute namespace
diff --git a/boost/compute/detail/meta_kernel.hpp b/boost/compute/detail/meta_kernel.hpp
index 5e6d6e0337..13af7cc437 100644
--- a/boost/compute/detail/meta_kernel.hpp
+++ b/boost/compute/detail/meta_kernel.hpp
@@ -1036,7 +1036,7 @@ inline meta_kernel& operator<<(meta_kernel &kernel,
}
// SVM requires OpenCL 2.0
-#if defined(CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+#if defined(BOOST_COMPUTE_CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
template<class T, class IndexExpr>
inline meta_kernel& operator<<(meta_kernel &kernel,
const svm_ptr_index_expr<T, IndexExpr> &expr)
@@ -1072,7 +1072,7 @@ inline meta_kernel& operator<<(meta_kernel &kernel,
BOOST_STATIC_ASSERT(N < 16);
if(N < 10){
- return kernel << expr.m_arg << ".s" << uint_(N);
+ return kernel << expr.m_arg << ".s" << int_(N);
}
else if(N < 16){
#ifdef _MSC_VER
diff --git a/boost/compute/detail/parameter_cache.hpp b/boost/compute/detail/parameter_cache.hpp
index 0a16cd9b0e..c609490c1e 100644
--- a/boost/compute/detail/parameter_cache.hpp
+++ b/boost/compute/detail/parameter_cache.hpp
@@ -24,6 +24,7 @@
#include <boost/compute/version.hpp>
#ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE
+#include <cstdio>
#include <boost/algorithm/string/trim.hpp>
#include <boost/compute/detail/path.hpp>
#include <boost/property_tree/ptree.hpp>
@@ -117,9 +118,16 @@ private:
static std::string version_string()
{
char buf[32];
- std::snprintf(buf, sizeof(buf), "%d.%d.%d", BOOST_COMPUTE_VERSION_MAJOR,
- BOOST_COMPUTE_VERSION_MINOR,
- BOOST_COMPUTE_VERSION_PATCH);
+ // snprintf is in Visual Studio since Visual Studio 2015 (_MSC_VER == 1900)
+ #if defined (_MSC_VER) && _MSC_VER < 1900
+ #define DETAIL_SNPRINTF sprintf_s
+ #else
+ #define DETAIL_SNPRINTF std::snprintf
+ #endif
+ DETAIL_SNPRINTF(buf, sizeof(buf), "%d.%d.%d", BOOST_COMPUTE_VERSION_MAJOR,
+ BOOST_COMPUTE_VERSION_MINOR,
+ BOOST_COMPUTE_VERSION_PATCH);
+ #undef DETAIL_SNPRINTF
return buf;
}
diff --git a/boost/compute/detail/path.hpp b/boost/compute/detail/path.hpp
index ec8760eaf9..d9c5afd182 100644
--- a/boost/compute/detail/path.hpp
+++ b/boost/compute/detail/path.hpp
@@ -30,7 +30,7 @@ static const std::string& path_delim()
// Path to appdata folder.
inline const std::string& appdata_path()
{
- #ifdef WIN32
+ #ifdef _WIN32
static const std::string appdata = detail::getenv("APPDATA")
+ path_delim() + "boost_compute";
#else
diff --git a/boost/compute/detail/read_write_single_value.hpp b/boost/compute/detail/read_write_single_value.hpp
index fde40d946c..3e613bc8c3 100644
--- a/boost/compute/detail/read_write_single_value.hpp
+++ b/boost/compute/detail/read_write_single_value.hpp
@@ -14,6 +14,7 @@
#include <boost/throw_exception.hpp>
#include <boost/compute/buffer.hpp>
+#include <boost/compute/event.hpp>
#include <boost/compute/exception.hpp>
#include <boost/compute/command_queue.hpp>
@@ -47,18 +48,18 @@ inline T read_single_value(const buffer &buffer, command_queue &queue)
// writes a single value at index to the buffer
template<class T>
-inline void write_single_value(const T &value,
- const buffer &buffer,
- size_t index,
- command_queue &queue)
+inline event write_single_value(const T &value,
+ const buffer &buffer,
+ size_t index,
+ command_queue &queue)
{
BOOST_ASSERT(index < buffer.size() / sizeof(T));
BOOST_ASSERT(buffer.get_context() == queue.get_context());
- queue.enqueue_write_buffer(buffer,
- index * sizeof(T),
- sizeof(T),
- &value);
+ return queue.enqueue_write_buffer(buffer,
+ index * sizeof(T),
+ sizeof(T),
+ &value);
}
// writes value to the first location in buffer
diff --git a/boost/compute/device.hpp b/boost/compute/device.hpp
index 5cf2e8c931..427d75d60b 100644
--- a/boost/compute/device.hpp
+++ b/boost/compute/device.hpp
@@ -62,7 +62,7 @@ public:
explicit device(cl_device_id id, bool retain = true)
: m_id(id)
{
- #ifdef CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
if(m_id && retain && is_subdevice()){
clRetainDevice(m_id);
}
@@ -75,7 +75,7 @@ public:
device(const device &other)
: m_id(other.m_id)
{
- #ifdef CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
if(m_id && is_subdevice()){
clRetainDevice(m_id);
}
@@ -86,7 +86,7 @@ public:
device& operator=(const device &other)
{
if(this != &other){
- #ifdef CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
if(m_id && is_subdevice()){
clReleaseDevice(m_id);
}
@@ -94,7 +94,7 @@ public:
m_id = other.m_id;
- #ifdef CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
if(m_id && is_subdevice()){
clRetainDevice(m_id);
}
@@ -115,7 +115,7 @@ public:
/// Move-assigns the device from \p other to \c *this.
device& operator=(device&& other) BOOST_NOEXCEPT
{
- #ifdef CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
if(m_id && is_subdevice()){
clReleaseDevice(m_id);
}
@@ -131,7 +131,7 @@ public:
/// Destroys the device object.
~device()
{
- #ifdef CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
if(m_id && is_subdevice()){
BOOST_COMPUTE_ASSERT_CL_SUCCESS(
clReleaseDevice(m_id)
@@ -282,7 +282,7 @@ public:
/// Returns \c true if the device is a sub-device.
bool is_subdevice() const
{
- #if defined(CL_VERSION_1_2)
+ #if defined(BOOST_COMPUTE_CL_VERSION_1_2)
try {
return get_info<cl_device_id>(CL_DEVICE_PARENT_DEVICE) != 0;
}
@@ -321,7 +321,7 @@ public:
typename detail::get_object_info_type<device, Enum>::type
get_info() const;
- #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ #if defined(BOOST_COMPUTE_CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
/// Partitions the device into multiple sub-devices according to
/// \p properties.
///
@@ -393,7 +393,7 @@ public:
return partition(properties);
}
- #endif // CL_VERSION_1_2
+ #endif // BOOST_COMPUTE_CL_VERSION_1_2
/// Returns \c true if the device is the same at \p other.
bool operator==(const device &other) const
@@ -528,7 +528,7 @@ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device,
)
#endif
-#ifdef CL_VERSION_1_1
+#ifdef BOOST_COMPUTE_CL_VERSION_1_1
BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device,
((bool, CL_DEVICE_HOST_UNIFIED_MEMORY))
((cl_uint, CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR))
@@ -539,9 +539,9 @@ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device,
((cl_uint, CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE))
((std::string, CL_DEVICE_OPENCL_C_VERSION))
)
-#endif // CL_VERSION_1_1
+#endif // BOOST_COMPUTE_CL_VERSION_1_1
-#ifdef CL_VERSION_1_2
+#ifdef BOOST_COMPUTE_CL_VERSION_1_2
BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device,
((std::string, CL_DEVICE_BUILT_IN_KERNELS))
((bool, CL_DEVICE_LINKER_AVAILABLE))
@@ -554,9 +554,9 @@ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device,
((bool, CL_DEVICE_PREFERRED_INTEROP_USER_SYNC))
((cl_uint, CL_DEVICE_REFERENCE_COUNT))
)
-#endif // CL_VERSION_1_2
+#endif // BOOST_COMPUTE_CL_VERSION_1_2
-#ifdef CL_VERSION_2_0
+#ifdef BOOST_COMPUTE_CL_VERSION_2_0
BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device,
((size_t, CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE))
((size_t, CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE))
@@ -576,7 +576,7 @@ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device,
((cl_uint, CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT))
((cl_uint, CL_DEVICE_IMAGE_PITCH_ALIGNMENT))
)
-#endif // CL_VERSION_2_0
+#endif // BOOST_COMPUTE_CL_VERSION_2_0
} // end compute namespace
} // end boost namespace
diff --git a/boost/compute/event.hpp b/boost/compute/event.hpp
index 2f53d87650..030c1bb3ba 100644
--- a/boost/compute/event.hpp
+++ b/boost/compute/event.hpp
@@ -74,7 +74,7 @@ public:
marker = CL_COMMAND_MARKER,
aquire_gl_objects = CL_COMMAND_ACQUIRE_GL_OBJECTS,
release_gl_object = CL_COMMAND_RELEASE_GL_OBJECTS
- #if defined(CL_VERSION_1_1)
+ #if defined(BOOST_COMPUTE_CL_VERSION_1_1)
,
read_buffer_rect = CL_COMMAND_READ_BUFFER_RECT,
write_buffer_rect = CL_COMMAND_WRITE_BUFFER_RECT,
@@ -218,7 +218,7 @@ public:
}
}
- #if defined(CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ #if defined(BOOST_COMPUTE_CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
/// Registers a function to be called when the event status changes to
/// \p status (by default CL_COMPLETE). The callback is passed the OpenCL
/// event object, the event status, and a pointer to arbitrary user data.
@@ -254,7 +254,7 @@ public:
new boost::function<void()>(callback)
);
}
- #endif // CL_VERSION_1_1
+ #endif // BOOST_COMPUTE_CL_VERSION_1_1
/// Returns the total duration of the event from \p start to \p end.
///
@@ -300,7 +300,7 @@ public:
}
private:
- #ifdef CL_VERSION_1_1
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_1
/// \internal_
static void BOOST_COMPUTE_CL_CALLBACK
event_callback_invoker(cl_event, cl_int, void *user_data)
@@ -312,7 +312,7 @@ private:
delete callback;
}
- #endif // CL_VERSION_1_1
+ #endif // BOOST_COMPUTE_CL_VERSION_1_1
protected:
cl_event m_event;
@@ -326,7 +326,7 @@ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(event,
((cl_uint, CL_EVENT_REFERENCE_COUNT))
)
-#ifdef CL_VERSION_1_1
+#ifdef BOOST_COMPUTE_CL_VERSION_1_1
BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(event,
((cl_context, CL_EVENT_CONTEXT))
)
diff --git a/boost/compute/exception/opencl_error.hpp b/boost/compute/exception/opencl_error.hpp
index 29a3a9d258..0f47b56f84 100644
--- a/boost/compute/exception/opencl_error.hpp
+++ b/boost/compute/exception/opencl_error.hpp
@@ -123,7 +123,7 @@ public:
case CL_INVALID_BUFFER_SIZE: return "Invalid Buffer Size";
case CL_INVALID_MIP_LEVEL: return "Invalid MIP Level";
case CL_INVALID_GLOBAL_WORK_SIZE: return "Invalid Global Work Size";
- #ifdef CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
case CL_COMPILE_PROGRAM_FAILURE: return "Compile Program Failure";
case CL_LINKER_NOT_AVAILABLE: return "Linker Not Available";
case CL_LINK_PROGRAM_FAILURE: return "Link Program Failure";
@@ -134,8 +134,8 @@ public:
case CL_INVALID_COMPILER_OPTIONS: return "Invalid Compiler Options";
case CL_INVALID_LINKER_OPTIONS: return "Invalid Linker Options";
case CL_INVALID_DEVICE_PARTITION_COUNT: return "Invalid Device Partition Count";
- #endif // CL_VERSION_1_2
- #ifdef CL_VERSION_2_0
+ #endif // BOOST_COMPUTE_CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_2_0
case CL_INVALID_PIPE_SIZE: return "Invalid Pipe Size";
case CL_INVALID_DEVICE_QUEUE: return "Invalid Device Queue";
#endif
diff --git a/boost/compute/function.hpp b/boost/compute/function.hpp
index b0b893e948..a731e18751 100644
--- a/boost/compute/function.hpp
+++ b/boost/compute/function.hpp
@@ -164,6 +164,19 @@ public:
m_definitions[name] = value;
}
+ bool operator==(const function<Signature>& other) const
+ {
+ return
+ (m_name == other.m_name)
+ && (m_definitions == other.m_definitions)
+ && (m_source == other.m_source);
+ }
+
+ bool operator!=(const function<Signature>& other) const
+ {
+ return !(*this == other);
+ }
+
/// \internal_
detail::invoked_function<result_type, boost::tuple<> >
operator()() const
diff --git a/boost/compute/functional/atomic.hpp b/boost/compute/functional/atomic.hpp
index 2701561bc3..ac4ac70d7f 100644
--- a/boost/compute/functional/atomic.hpp
+++ b/boost/compute/functional/atomic.hpp
@@ -15,7 +15,7 @@
#include <boost/compute/function.hpp>
#ifndef BOOST_COMPUTE_DOXYGEN_INVOKED
-#ifdef CL_VERSION_1_1
+#ifdef BOOST_COMPUTE_CL_VERSION_1_1
#define BOOST_COMPUTE_DETAIL_ATOMIC_PREFIX "atomic_"
#else
#define BOOST_COMPUTE_DETAIL_ATOMIC_PREFIX "atom_"
diff --git a/boost/compute/image/image1d.hpp b/boost/compute/image/image1d.hpp
index 2d71934ab4..0f146be089 100644
--- a/boost/compute/image/image1d.hpp
+++ b/boost/compute/image/image1d.hpp
@@ -50,7 +50,7 @@ public:
cl_mem_flags flags = read_write,
void *host_ptr = 0)
{
- #ifdef CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
cl_image_desc desc;
desc.image_type = CL_MEM_OBJECT_IMAGE1D;
desc.image_width = image_width;
@@ -61,7 +61,7 @@ public:
desc.image_slice_pitch = 0;
desc.num_mip_levels = 0;
desc.num_samples = 0;
- #ifdef CL_VERSION_2_0
+ #ifdef BOOST_COMPUTE_CL_VERSION_2_0
desc.mem_object = 0;
#else
desc.buffer = 0;
@@ -151,7 +151,7 @@ public:
static std::vector<image_format>
get_supported_formats(const context &context, cl_mem_flags flags = read_write)
{
- #ifdef CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
return image_object::get_supported_formats(context, CL_MEM_OBJECT_IMAGE1D, flags);
#else
return std::vector<image_format>();
@@ -164,7 +164,7 @@ public:
const context &context,
cl_mem_flags flags = read_write)
{
- #ifdef CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
return image_object::is_supported_format(
format, context, CL_MEM_OBJECT_IMAGE1D, flags
);
diff --git a/boost/compute/image/image2d.hpp b/boost/compute/image/image2d.hpp
index c203a9417f..edfe98de5a 100644
--- a/boost/compute/image/image2d.hpp
+++ b/boost/compute/image/image2d.hpp
@@ -58,7 +58,7 @@ public:
{
cl_int error = 0;
- #ifdef CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
cl_image_desc desc;
desc.image_type = CL_MEM_OBJECT_IMAGE2D;
desc.image_width = image_width;
@@ -69,7 +69,7 @@ public:
desc.image_slice_pitch = 0;
desc.num_mip_levels = 0;
desc.num_samples = 0;
- #ifdef CL_VERSION_2_0
+ #ifdef BOOST_COMPUTE_CL_VERSION_2_0
desc.mem_object = 0;
#else
desc.buffer = 0;
@@ -108,7 +108,7 @@ public:
{
cl_int error = 0;
- #ifdef CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
cl_image_desc desc;
desc.image_type = CL_MEM_OBJECT_IMAGE2D;
desc.image_width = image_width;
@@ -119,7 +119,7 @@ public:
desc.image_slice_pitch = 0;
desc.num_mip_levels = 0;
desc.num_samples = 0;
- #ifdef CL_VERSION_2_0
+ #ifdef BOOST_COMPUTE_CL_VERSION_2_0
desc.mem_object = 0;
#else
desc.buffer = 0;
diff --git a/boost/compute/image/image3d.hpp b/boost/compute/image/image3d.hpp
index 9463cfaa16..5569f2a0b9 100644
--- a/boost/compute/image/image3d.hpp
+++ b/boost/compute/image/image3d.hpp
@@ -54,7 +54,7 @@ public:
{
cl_int error = 0;
- #ifdef CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
cl_image_desc desc;
desc.image_type = CL_MEM_OBJECT_IMAGE3D;
desc.image_width = image_width;
@@ -65,7 +65,7 @@ public:
desc.image_slice_pitch = image_slice_pitch;
desc.num_mip_levels = 0;
desc.num_samples = 0;
- #ifdef CL_VERSION_2_0
+ #ifdef BOOST_COMPUTE_CL_VERSION_2_0
desc.mem_object = 0;
#else
desc.buffer = 0;
@@ -108,7 +108,7 @@ public:
{
cl_int error = 0;
- #ifdef CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
cl_image_desc desc;
desc.image_type = CL_MEM_OBJECT_IMAGE3D;
desc.image_width = image_width;
@@ -119,7 +119,7 @@ public:
desc.image_slice_pitch = image_slice_pitch;
desc.num_mip_levels = 0;
desc.num_samples = 0;
- #ifdef CL_VERSION_2_0
+ #ifdef BOOST_COMPUTE_CL_VERSION_2_0
desc.mem_object = 0;
#else
desc.buffer = 0;
diff --git a/boost/compute/image/image_sampler.hpp b/boost/compute/image/image_sampler.hpp
index 4f1bfe9b86..26f20aa9d5 100644
--- a/boost/compute/image/image_sampler.hpp
+++ b/boost/compute/image/image_sampler.hpp
@@ -55,7 +55,7 @@ public:
{
cl_int error = 0;
- #ifdef CL_VERSION_2_0
+ #ifdef BOOST_COMPUTE_CL_VERSION_2_0
std::vector<cl_sampler_properties> sampler_properties;
sampler_properties.push_back(CL_SAMPLER_NORMALIZED_COORDS);
sampler_properties.push_back(cl_sampler_properties(normalized_coords));
diff --git a/boost/compute/interop/opengl/context.hpp b/boost/compute/interop/opengl/context.hpp
index c35fedddfa..077c86036b 100644
--- a/boost/compute/interop/opengl/context.hpp
+++ b/boost/compute/interop/opengl/context.hpp
@@ -75,6 +75,10 @@ inline context opengl_create_shared_context()
for(size_t i = 0; i < platforms.size(); i++){
const platform &platform = platforms[i];
+ // check whether this platform supports OpenCL/OpenGL sharing
+ if (!platform.supports_extension(cl_gl_sharing_extension))
+ continue;
+
// load clGetGLContextInfoKHR() extension function
GetGLContextInfoKHRFunction GetGLContextInfoKHR =
reinterpret_cast<GetGLContextInfoKHRFunction>(
@@ -92,7 +96,7 @@ inline context opengl_create_shared_context()
#if defined(__linux__)
CL_GL_CONTEXT_KHR, (cl_context_properties) glXGetCurrentContext(),
CL_GLX_DISPLAY_KHR, (cl_context_properties) glXGetCurrentDisplay(),
- #elif defined(WIN32)
+ #elif defined(_WIN32)
CL_GL_CONTEXT_KHR, (cl_context_properties) wglGetCurrentContext(),
CL_WGL_HDC_KHR, (cl_context_properties) wglGetCurrentDC(),
#endif
diff --git a/boost/compute/interop/opengl/opengl_texture.hpp b/boost/compute/interop/opengl/opengl_texture.hpp
index c1f3f4f441..ae095d22a9 100644
--- a/boost/compute/interop/opengl/opengl_texture.hpp
+++ b/boost/compute/interop/opengl/opengl_texture.hpp
@@ -51,7 +51,7 @@ public:
{
cl_int error = 0;
- #ifdef CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
m_mem = clCreateFromGLTexture(context,
flags,
texture_target,
diff --git a/boost/compute/iterator/buffer_iterator.hpp b/boost/compute/iterator/buffer_iterator.hpp
index cd68058f64..de2395a552 100644
--- a/boost/compute/iterator/buffer_iterator.hpp
+++ b/boost/compute/iterator/buffer_iterator.hpp
@@ -58,13 +58,20 @@ struct buffer_iterator_index_expr
size_t index,
const memory_object::address_space address_space,
const IndexExpr &expr)
- : m_buffer(buffer),
+ : m_buffer(buffer.get(), false),
m_index(index),
m_address_space(address_space),
m_expr(expr)
{
}
+ ~buffer_iterator_index_expr()
+ {
+ // set buffer to null so that its reference count will
+ // not be decremented when its destructor is called
+ m_buffer.get() = 0;
+ }
+
operator T() const
{
BOOST_STATIC_ASSERT_MSG(boost::is_integral<IndexExpr>::value,
@@ -73,10 +80,10 @@ struct buffer_iterator_index_expr
return buffer_value<T>(m_buffer, size_t(m_expr) * sizeof(T));
}
- const buffer &m_buffer;
- size_t m_index;
- memory_object::address_space m_address_space;
- IndexExpr m_expr;
+ const buffer m_buffer;
+ const size_t m_index;
+ const memory_object::address_space m_address_space;
+ const IndexExpr m_expr;
};
template<class T, class IndexExpr>
diff --git a/boost/compute/iterator/counting_iterator.hpp b/boost/compute/iterator/counting_iterator.hpp
index 304c1e05cf..384486bcb3 100644
--- a/boost/compute/iterator/counting_iterator.hpp
+++ b/boost/compute/iterator/counting_iterator.hpp
@@ -47,14 +47,14 @@ struct counting_iterator_index_expr
{
typedef T result_type;
- counting_iterator_index_expr(const T &init, const IndexExpr &expr)
+ counting_iterator_index_expr(const T init, const IndexExpr &expr)
: m_init(init),
m_expr(expr)
{
}
- const T &m_init;
- IndexExpr m_expr;
+ const T m_init;
+ const IndexExpr m_expr;
};
template<class T, class IndexExpr>
diff --git a/boost/compute/iterator/function_input_iterator.hpp b/boost/compute/iterator/function_input_iterator.hpp
index bd89b6c0fc..bb8f0d5d09 100644
--- a/boost/compute/iterator/function_input_iterator.hpp
+++ b/boost/compute/iterator/function_input_iterator.hpp
@@ -53,7 +53,7 @@ struct function_input_iterator_expr
{
}
- Function m_function;
+ const Function m_function;
};
template<class Function>
diff --git a/boost/compute/iterator/permutation_iterator.hpp b/boost/compute/iterator/permutation_iterator.hpp
index 8a7f97a402..a0d2dbfbc5 100644
--- a/boost/compute/iterator/permutation_iterator.hpp
+++ b/boost/compute/iterator/permutation_iterator.hpp
@@ -60,9 +60,9 @@ struct permutation_iterator_access_expr
{
}
- ElementIterator m_element_iter;
- IndexIterator m_index_iter;
- IndexExpr m_expr;
+ const ElementIterator m_element_iter;
+ const IndexIterator m_index_iter;
+ const IndexExpr m_expr;
};
template<class ElementIterator, class IndexIterator, class IndexExpr>
diff --git a/boost/compute/iterator/strided_iterator.hpp b/boost/compute/iterator/strided_iterator.hpp
index 52e7f07bd8..eb342dc33d 100644
--- a/boost/compute/iterator/strided_iterator.hpp
+++ b/boost/compute/iterator/strided_iterator.hpp
@@ -56,8 +56,8 @@ struct stride_expr
{
}
- IndexExpr m_index_expr;
- Stride m_stride;
+ const IndexExpr m_index_expr;
+ const Stride m_stride;
};
template<class IndexExpr, class Stride>
@@ -90,9 +90,9 @@ struct strided_iterator_index_expr
{
}
- Iterator m_input_iter;
- const Stride& m_stride;
- IndexExpr m_index_expr;
+ const Iterator m_input_iter;
+ const Stride m_stride;
+ const IndexExpr m_index_expr;
};
template<class Iterator, class Stride, class IndexExpr>
diff --git a/boost/compute/iterator/transform_iterator.hpp b/boost/compute/iterator/transform_iterator.hpp
index c040922f9d..08ff6ee4d4 100644
--- a/boost/compute/iterator/transform_iterator.hpp
+++ b/boost/compute/iterator/transform_iterator.hpp
@@ -76,9 +76,9 @@ struct transform_iterator_index_expr
{
}
- InputIterator m_input_iter;
- UnaryFunction m_transform_expr;
- IndexExpr m_index_expr;
+ const InputIterator m_input_iter;
+ const UnaryFunction m_transform_expr;
+ const IndexExpr m_index_expr;
};
template<class InputIterator, class UnaryFunction, class IndexExpr>
diff --git a/boost/compute/iterator/zip_iterator.hpp b/boost/compute/iterator/zip_iterator.hpp
index 2860d73a93..a4af6a3034 100644
--- a/boost/compute/iterator/zip_iterator.hpp
+++ b/boost/compute/iterator/zip_iterator.hpp
@@ -92,8 +92,8 @@ struct zip_iterator_index_expr
{
}
- IteratorTuple m_iterators;
- IndexExpr m_index_expr;
+ const IteratorTuple m_iterators;
+ const IndexExpr m_index_expr;
};
/// \internal_
diff --git a/boost/compute/kernel.hpp b/boost/compute/kernel.hpp
index 72f21a0378..097cba692e 100644
--- a/boost/compute/kernel.hpp
+++ b/boost/compute/kernel.hpp
@@ -168,7 +168,7 @@ public:
typename detail::get_object_info_type<kernel, Enum>::type
get_info() const;
- #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ #if defined(BOOST_COMPUTE_CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
/// Returns information about the argument at \p index.
///
/// For example, to get the name of the first argument:
@@ -197,7 +197,7 @@ public:
template<int Enum>
typename detail::get_object_info_type<kernel, Enum>::type
get_arg_info(size_t index) const;
- #endif // CL_VERSION_1_2
+ #endif // BOOST_COMPUTE_CL_VERSION_1_2
/// Returns work-group information for the kernel with \p device.
///
@@ -266,7 +266,7 @@ public:
/// \internal_
void set_arg_svm_ptr(size_t index, void* ptr)
{
- #ifdef CL_VERSION_2_0
+ #ifdef BOOST_COMPUTE_CL_VERSION_2_0
cl_int ret = clSetKernelArgSVMPointer(m_kernel, static_cast<cl_uint>(index), ptr);
if(ret != CL_SUCCESS){
BOOST_THROW_EXCEPTION(opencl_error(ret));
@@ -289,7 +289,7 @@ public:
}
#endif // BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
- #if defined(CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ #if defined(BOOST_COMPUTE_CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
/// Sets additional execution information for the kernel.
///
/// \opencl_version_warning{2,0}
@@ -302,7 +302,7 @@ public:
BOOST_THROW_EXCEPTION(opencl_error(ret));
}
}
- #endif // CL_VERSION_2_0
+ #endif // BOOST_COMPUTE_CL_VERSION_2_0
/// Returns \c true if the kernel is the same at \p other.
bool operator==(const kernel &other) const
@@ -365,14 +365,14 @@ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(kernel,
((cl_program, CL_KERNEL_PROGRAM))
)
-#ifdef CL_VERSION_1_2
+#ifdef BOOST_COMPUTE_CL_VERSION_1_2
BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(kernel,
((std::string, CL_KERNEL_ATTRIBUTES))
)
-#endif // CL_VERSION_1_2
+#endif // BOOST_COMPUTE_CL_VERSION_1_2
/// \internal_ define get_arg_info() specializations for kernel
-#ifdef CL_VERSION_1_2
+#ifdef BOOST_COMPUTE_CL_VERSION_1_2
#define BOOST_COMPUTE_DETAIL_DEFINE_KERNEL_GET_ARG_INFO_SPECIALIZATION(result_type, value) \
namespace detail { \
template<> struct get_object_info_type<kernel, value> { typedef result_type type; }; \
@@ -386,7 +386,7 @@ BOOST_COMPUTE_DETAIL_DEFINE_KERNEL_GET_ARG_INFO_SPECIALIZATION(cl_kernel_arg_acc
BOOST_COMPUTE_DETAIL_DEFINE_KERNEL_GET_ARG_INFO_SPECIALIZATION(std::string, CL_KERNEL_ARG_TYPE_NAME)
BOOST_COMPUTE_DETAIL_DEFINE_KERNEL_GET_ARG_INFO_SPECIALIZATION(cl_kernel_arg_type_qualifier, CL_KERNEL_ARG_TYPE_QUALIFIER)
BOOST_COMPUTE_DETAIL_DEFINE_KERNEL_GET_ARG_INFO_SPECIALIZATION(std::string, CL_KERNEL_ARG_NAME)
-#endif // CL_VERSION_1_2
+#endif // BOOST_COMPUTE_CL_VERSION_1_2
namespace detail {
diff --git a/boost/compute/lambda/context.hpp b/boost/compute/lambda/context.hpp
index ed25b79475..a7248d4639 100644
--- a/boost/compute/lambda/context.hpp
+++ b/boost/compute/lambda/context.hpp
@@ -78,6 +78,41 @@ struct context : proto::callable_context<context<Args> >
stream << stream.lit(x);
}
+ void operator()(proto::tag::terminal, const uchar_ &x)
+ {
+ stream << "(uchar)(" << stream.lit(uint_(x)) << "u)";
+ }
+
+ void operator()(proto::tag::terminal, const char_ &x)
+ {
+ stream << "(char)(" << stream.lit(int_(x)) << ")";
+ }
+
+ void operator()(proto::tag::terminal, const ushort_ &x)
+ {
+ stream << "(ushort)(" << stream.lit(x) << "u)";
+ }
+
+ void operator()(proto::tag::terminal, const short_ &x)
+ {
+ stream << "(short)(" << stream.lit(x) << ")";
+ }
+
+ void operator()(proto::tag::terminal, const uint_ &x)
+ {
+ stream << "(" << stream.lit(x) << "u)";
+ }
+
+ void operator()(proto::tag::terminal, const ulong_ &x)
+ {
+ stream << "(" << stream.lit(x) << "ul)";
+ }
+
+ void operator()(proto::tag::terminal, const long_ &x)
+ {
+ stream << "(" << stream.lit(x) << "l)";
+ }
+
// handle placeholders
template<int I>
void operator()(proto::tag::terminal, placeholder<I>)
diff --git a/boost/compute/lambda/functional.hpp b/boost/compute/lambda/functional.hpp
index dd7190e4d9..42e75e4991 100644
--- a/boost/compute/lambda/functional.hpp
+++ b/boost/compute/lambda/functional.hpp
@@ -22,6 +22,11 @@
#include <boost/compute/lambda/result_of.hpp>
#include <boost/compute/lambda/placeholder.hpp>
+#include <boost/compute/types/fundamental.hpp>
+#include <boost/compute/type_traits/scalar_type.hpp>
+#include <boost/compute/type_traits/vector_size.hpp>
+#include <boost/compute/type_traits/make_vector_type.hpp>
+
namespace boost {
namespace compute {
namespace lambda {
@@ -29,7 +34,8 @@ namespace lambda {
namespace mpl = boost::mpl;
namespace proto = boost::proto;
-// wraps a unary boolean function
+// wraps a unary boolean function whose result type is an int_ when the argument
+// type is a scalar, and intN_ if the argument type is a vector of size N
#define BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(name) \
namespace detail { \
struct BOOST_PP_CAT(name, _func) \
@@ -37,7 +43,12 @@ namespace proto = boost::proto;
template<class Expr, class Args> \
struct lambda_result \
{ \
- typedef int type; \
+ typedef typename proto::result_of::child_c<Expr, 1>::type Arg; \
+ typedef typename ::boost::compute::lambda::result_of<Arg, Args>::type result_type; \
+ typedef typename ::boost::compute::make_vector_type< \
+ ::boost::compute::int_, \
+ ::boost::compute::vector_size<result_type>::value \
+ >::type type; \
}; \
\
template<class Context, class Arg> \
@@ -60,7 +71,7 @@ namespace proto = boost::proto;
); \
}
-// wraps a unary function who's return type is the same as the argument type
+// wraps a unary function whose return type is the same as the argument type
#define BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(name) \
namespace detail { \
struct BOOST_PP_CAT(name, _func) \
@@ -92,7 +103,79 @@ namespace proto = boost::proto;
); \
}
-// wraps a binary function
+// wraps a unary function whose result type is the scalar type of the first argument
+#define BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_ST(name) \
+ namespace detail { \
+ struct BOOST_PP_CAT(name, _func) \
+ { \
+ template<class Expr, class Args> \
+ struct lambda_result \
+ { \
+ typedef typename proto::result_of::child_c<Expr, 1>::type Arg; \
+ typedef typename ::boost::compute::lambda::result_of<Arg, Args>::type result_type; \
+ typedef typename ::boost::compute::scalar_type<result_type>::type type; \
+ }; \
+ \
+ template<class Context, class Arg> \
+ static void apply(Context &ctx, const Arg &arg) \
+ { \
+ ctx.stream << #name << "("; \
+ proto::eval(arg, ctx); \
+ ctx.stream << ")"; \
+ } \
+ }; \
+ } \
+ template<class Arg> \
+ inline typename proto::result_of::make_expr< \
+ proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg& \
+ >::type const \
+ name(const Arg &arg) \
+ { \
+ return proto::make_expr<proto::tag::function>( \
+ BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg) \
+ ); \
+ }
+
+// wraps a binary boolean function whose result type is an int_ when the first
+// argument type is a scalar, and intN_ if the first argument type is a vector
+// of size N
+#define BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_BINARY_FUNCTION(name) \
+ namespace detail { \
+ struct BOOST_PP_CAT(name, _func) \
+ { \
+ template<class Expr, class Args> \
+ struct lambda_result \
+ { \
+ typedef typename proto::result_of::child_c<Expr, 1>::type Arg1; \
+ typedef typename ::boost::compute::make_vector_type< \
+ ::boost::compute::int_, \
+ ::boost::compute::vector_size<Arg1>::value \
+ >::type type; \
+ }; \
+ \
+ template<class Context, class Arg1, class Arg2> \
+ static void apply(Context &ctx, const Arg1 &arg1, const Arg2 &arg2) \
+ { \
+ ctx.stream << #name << "("; \
+ proto::eval(arg1, ctx); \
+ ctx.stream << ", "; \
+ proto::eval(arg2, ctx); \
+ ctx.stream << ")"; \
+ } \
+ }; \
+ } \
+ template<class Arg1, class Arg2> \
+ inline typename proto::result_of::make_expr< \
+ proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg1&, const Arg2& \
+ >::type const \
+ name(const Arg1 &arg1, const Arg2 &arg2) \
+ { \
+ return proto::make_expr<proto::tag::function>( \
+ BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg1), ::boost::ref(arg2) \
+ ); \
+ }
+
+// wraps a binary function whose result type is the type of the first argument
#define BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(name) \
namespace detail { \
struct BOOST_PP_CAT(name, _func) \
@@ -126,6 +209,40 @@ namespace proto = boost::proto;
); \
}
+// wraps a binary function whose result type is the type of the second argument
+#define BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_2(name) \
+ namespace detail { \
+ struct BOOST_PP_CAT(name, _func) \
+ { \
+ template<class Expr, class Args> \
+ struct lambda_result \
+ { \
+ typedef typename proto::result_of::child_c<Expr, 2>::type Arg2; \
+ typedef typename ::boost::compute::lambda::result_of<Arg2, Args>::type type; \
+ }; \
+ \
+ template<class Context, class Arg1, class Arg2> \
+ static void apply(Context &ctx, const Arg1 &arg1, const Arg2 &arg2) \
+ { \
+ ctx.stream << #name << "("; \
+ proto::eval(arg1, ctx); \
+ ctx.stream << ", "; \
+ proto::eval(arg2, ctx); \
+ ctx.stream << ")"; \
+ } \
+ }; \
+ } \
+ template<class Arg1, class Arg2> \
+ inline typename proto::result_of::make_expr< \
+ proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg1&, const Arg2& \
+ >::type const \
+ name(const Arg1 &arg1, const Arg2 &arg2) \
+ { \
+ return proto::make_expr<proto::tag::function>( \
+ BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg1), ::boost::ref(arg2) \
+ ); \
+ }
+
// wraps a binary function who's result type is the scalar type of the first argument
#define BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_ST(name) \
namespace detail { \
@@ -161,6 +278,41 @@ namespace proto = boost::proto;
); \
}
+// wraps a binary function whose result type is the type of the first argument
+// and the second argument is a pointer
+#define BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_PTR(name) \
+ namespace detail { \
+ struct BOOST_PP_CAT(name, _func) \
+ { \
+ template<class Expr, class Args> \
+ struct lambda_result \
+ { \
+ typedef typename proto::result_of::child_c<Expr, 1>::type Arg1; \
+ typedef typename ::boost::compute::lambda::result_of<Arg1, Args>::type type; \
+ }; \
+ \
+ template<class Context, class Arg1, class Arg2> \
+ static void apply(Context &ctx, const Arg1 &arg1, const Arg2 &arg2) \
+ { \
+ ctx.stream << #name << "("; \
+ proto::eval(arg1, ctx); \
+ ctx.stream << ", &"; \
+ proto::eval(arg2, ctx); \
+ ctx.stream << ")"; \
+ } \
+ }; \
+ } \
+ template<class Arg1, class Arg2> \
+ inline typename proto::result_of::make_expr< \
+ proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg1&, const Arg2& \
+ >::type const \
+ name(const Arg1 &arg1, const Arg2 &arg2) \
+ { \
+ return proto::make_expr<proto::tag::function>( \
+ BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg1), ::boost::ref(arg2) \
+ ); \
+ }
+
// wraps a ternary function
#define BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(name) \
namespace detail { \
@@ -197,43 +349,246 @@ namespace proto = boost::proto;
); \
}
+// wraps a ternary function whose result type is the type of the third argument
+#define BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION_3(name) \
+ namespace detail { \
+ struct BOOST_PP_CAT(name, _func) \
+ { \
+ template<class Expr, class Args> \
+ struct lambda_result \
+ { \
+ typedef typename proto::result_of::child_c<Expr, 3>::type Arg3; \
+ typedef typename ::boost::compute::lambda::result_of<Arg3, Args>::type type; \
+ }; \
+ \
+ template<class Context, class Arg1, class Arg2, class Arg3> \
+ static void apply(Context &ctx, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) \
+ { \
+ ctx.stream << #name << "("; \
+ proto::eval(arg1, ctx); \
+ ctx.stream << ", "; \
+ proto::eval(arg2, ctx); \
+ ctx.stream << ", "; \
+ proto::eval(arg3, ctx); \
+ ctx.stream << ")"; \
+ } \
+ }; \
+ } \
+ template<class Arg1, class Arg2, class Arg3> \
+ inline typename proto::result_of::make_expr< \
+ proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg1&, const Arg2&, const Arg3& \
+ >::type const \
+ name(const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) \
+ { \
+ return proto::make_expr<proto::tag::function>( \
+ BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg1), ::boost::ref(arg2), ::boost::ref(arg3) \
+ ); \
+ }
-BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(all)
-BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(any)
-BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(isinf)
-BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(isnan)
-BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(isfinite)
+// wraps a ternary function whose result type is the type of the first argument
+// and the third argument of the function is a pointer
+#define BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION_PTR(name) \
+ namespace detail { \
+ struct BOOST_PP_CAT(name, _func) \
+ { \
+ template<class Expr, class Args> \
+ struct lambda_result \
+ { \
+ typedef typename proto::result_of::child_c<Expr, 3>::type Arg3; \
+ typedef typename ::boost::compute::lambda::result_of<Arg3, Args>::type type; \
+ }; \
+ \
+ template<class Context, class Arg1, class Arg2, class Arg3> \
+ static void apply(Context &ctx, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) \
+ { \
+ ctx.stream << #name << "("; \
+ proto::eval(arg1, ctx); \
+ ctx.stream << ", "; \
+ proto::eval(arg2, ctx); \
+ ctx.stream << ", &"; \
+ proto::eval(arg3, ctx); \
+ ctx.stream << ")"; \
+ } \
+ }; \
+ } \
+ template<class Arg1, class Arg2, class Arg3> \
+ inline typename proto::result_of::make_expr< \
+ proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg1&, const Arg2&, const Arg3& \
+ >::type const \
+ name(const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) \
+ { \
+ return proto::make_expr<proto::tag::function>( \
+ BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg1), ::boost::ref(arg2), ::boost::ref(arg3) \
+ ); \
+ }
+// Common Built-In Functions
+BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(clamp)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(degrees)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(min)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(max)
+BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(mix)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(radians)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(sign)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_2(step)
+BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION_3(smoothstep)
+
+// Geometric Built-In Functions
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(cross)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_ST(dot)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_ST(distance)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_ST(length)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(normalize)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_ST(fast_distance)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_ST(fast_length)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(fast_normalize)
+
+// Integer Built-In Functions
BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(abs)
-BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(cos)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(abs_diff)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(add_sat)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(hadd)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(rhadd)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(clz)
+#ifdef BOOST_COMPUTE_CL_VERSION_2_0
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(ctz)
+#endif
+// clamp() (since 1.1) already defined in common
+BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(mad_hi)
+BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(mad24)
+BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(mad_sat)
+// max() and min() functions are defined in common
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(mul_hi)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(mul24)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(rotate)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(sub_sat)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(upsample)
+#ifdef BOOST_COMPUTE_CL_VERSION_1_2
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(popcount)
+#endif
+
+// Math Built-In Functions
BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(acos)
-BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(sin)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(acosh)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(acospi)
BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(asin)
-BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(tan)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(asinh)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(asinpi)
BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(atan)
-BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(sqrt)
-BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(rsqrt)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(atan2)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(atanh)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(atanpi)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(atan2pi)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(cbrt)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(ceil)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(copysign)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(cos)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(cosh)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(cospi)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(erfc)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(erf)
BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(exp)
BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(exp2)
BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(exp10)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(expm1)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(fabs)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(fdim)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(floor)
+BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(fma)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(fmax)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(fmin)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(fmod)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_PTR(fract)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_PTR(frexp)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(hypot)
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_BINARY_FUNCTION(ilogb) // ilogb returns intN_
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(ldexp)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(lgamma)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_PTR(lgamma_r)
BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(log)
BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(log2)
BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(log10)
-BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(round)
-BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(length)
-
-BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(cross)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(log1p)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(logb)
+BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(mad)
+#ifdef BOOST_COMPUTE_CL_VERSION_1_1
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(maxmag)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(minmag)
+#endif
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_PTR(modf)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(nan)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(nextafter)
BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(pow)
BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(pown)
BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(powr)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(remainder)
+BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION_PTR(remquo)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(rint)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(rootn)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(round)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(rsqrt)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(sin)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(sincos)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(sinh)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(sinpi)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(sqrt)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(tan)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(tanh)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(tanpi)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(tgamma)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(trunc)
-BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_ST(dot)
-BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_ST(distance)
+// Native Math Built-In Functions
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(native_cos)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(native_divide)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(native_exp)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(native_exp2)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(native_exp10)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(native_log)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(native_log2)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(native_log10)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(native_powr)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(native_recip)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(native_rsqrt)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(native_sin)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(native_sqrt)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(native_tan)
-BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(clamp)
-BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(fma)
-BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(mad)
-BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(smoothstep)
+// Half Math Built-In Functions
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(half_cos)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(half_divide)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(half_exp)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(half_exp2)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(half_exp10)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(half_log)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(half_log2)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(half_log10)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(half_powr)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(half_recip)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(half_rsqrt)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(half_sin)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(half_sqrt)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(half_tan)
+
+// Relational Built-In Functions
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_BINARY_FUNCTION(isequal)
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_BINARY_FUNCTION(isnotequal)
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_BINARY_FUNCTION(isgreater)
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_BINARY_FUNCTION(isgreaterequal)
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_BINARY_FUNCTION(isless)
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_BINARY_FUNCTION(islessequal)
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_BINARY_FUNCTION(islessgreater)
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(isfinite)
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(isinf)
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(isnan)
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(isnormal)
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_BINARY_FUNCTION(isordered)
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_BINARY_FUNCTION(isunordered)
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(singbit)
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(all)
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(any)
+BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(bitselect)
+BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(select)
} // end lambda namespace
} // end compute namespace
diff --git a/boost/compute/memory/svm_ptr.hpp b/boost/compute/memory/svm_ptr.hpp
index 0c9d88035c..c8753f5b34 100644
--- a/boost/compute/memory/svm_ptr.hpp
+++ b/boost/compute/memory/svm_ptr.hpp
@@ -29,7 +29,7 @@ template<class T>
class svm_ptr;
// svm functions require OpenCL 2.0
-#if defined(CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+#if defined(BOOST_COMPUTE_CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
namespace detail {
template<class T, class IndexExpr>
@@ -131,8 +131,18 @@ public:
return m_context;
}
+ bool operator==(const svm_ptr<T>& other) const
+ {
+ return (other.m_context == m_context) && (m_ptr == other.m_ptr);
+ }
+
+ bool operator!=(const svm_ptr<T>& other) const
+ {
+ return (other.m_context != m_context) || (m_ptr != other.m_ptr);
+ }
+
// svm functions require OpenCL 2.0
- #if defined(CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ #if defined(BOOST_COMPUTE_CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
/// \internal_
template<class Expr>
detail::svm_ptr_index_expr<T, Expr>
diff --git a/boost/compute/memory_object.hpp b/boost/compute/memory_object.hpp
index 14c4cf4c7e..75c8738f8f 100644
--- a/boost/compute/memory_object.hpp
+++ b/boost/compute/memory_object.hpp
@@ -38,7 +38,7 @@ public:
use_host_ptr = CL_MEM_USE_HOST_PTR,
alloc_host_ptr = CL_MEM_ALLOC_HOST_PTR,
copy_host_ptr = CL_MEM_COPY_HOST_PTR
- #ifdef CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
,
host_write_only = CL_MEM_HOST_WRITE_ONLY,
host_read_only = CL_MEM_HOST_READ_ONLY,
@@ -105,7 +105,7 @@ public:
return detail::get_object_info<T>(clGetMemObjectInfo, m_mem, info);
}
- #if defined(CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ #if defined(BOOST_COMPUTE_CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
/// Registers a function to be called when the memory object is deleted
/// and its resources freed.
///
@@ -137,7 +137,7 @@ public:
new boost::function<void()>(callback)
);
}
- #endif // CL_VERSION_1_1
+ #endif // BOOST_COMPUTE_CL_VERSION_1_1
/// Returns \c true if the memory object is the same as \p other.
bool operator==(const memory_object &other) const
@@ -152,7 +152,7 @@ public:
}
private:
- #ifdef CL_VERSION_1_1
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_1
/// \internal_
static void BOOST_COMPUTE_CL_CALLBACK
destructor_callback_invoker(cl_mem, void *user_data)
@@ -164,7 +164,7 @@ private:
delete callback;
}
- #endif // CL_VERSION_1_1
+ #endif // BOOST_COMPUTE_CL_VERSION_1_1
protected:
/// \internal_
diff --git a/boost/compute/pipe.hpp b/boost/compute/pipe.hpp
index 944674e622..907750a3ba 100644
--- a/boost/compute/pipe.hpp
+++ b/boost/compute/pipe.hpp
@@ -18,7 +18,7 @@
#include <boost/compute/detail/get_object_info.hpp>
// pipe objects require opencl 2.0
-#if defined(CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+#if defined(BOOST_COMPUTE_CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
namespace boost {
namespace compute {
@@ -149,6 +149,6 @@ struct set_kernel_arg<pipe>
} // end compute namespace
} // end boost namespace
-#endif // CL_VERSION_2_0
+#endif // BOOST_COMPUTE_CL_VERSION_2_0
#endif // BOOST_COMPUTE_PIPE_HPP
diff --git a/boost/compute/platform.hpp b/boost/compute/platform.hpp
index 65fda84e11..fddfec8c11 100644
--- a/boost/compute/platform.hpp
+++ b/boost/compute/platform.hpp
@@ -181,7 +181,7 @@ public:
/// function. Returns \c 0 if \p function_name is invalid.
void* get_extension_function_address(const char *function_name) const
{
- #ifdef CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
return clGetExtensionFunctionAddressForPlatform(m_platform,
function_name);
#else
@@ -192,7 +192,7 @@ public:
/// Requests that the platform unload any compiler resources.
void unload_compiler()
{
- #ifdef CL_VERSION_1_2
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
clUnloadPlatformCompiler(m_platform);
#else
clUnloadCompiler();
diff --git a/boost/compute/program.hpp b/boost/compute/program.hpp
index 7573aa02e6..e953d7a89e 100644
--- a/boost/compute/program.hpp
+++ b/boost/compute/program.hpp
@@ -272,13 +272,15 @@ public:
}
}
- #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ #if defined(BOOST_COMPUTE_CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
/// Compiles the program with \p options.
///
/// \opencl_version_warning{1,2}
///
/// \see_opencl_ref{clCompileProgram}
- void compile(const std::string &options = std::string())
+ void compile(const std::string &options = std::string(),
+ const std::vector<std::pair<std::string, program> > &headers =
+ std::vector<std::pair<std::string, program> >())
{
const char *options_string = 0;
@@ -286,9 +288,36 @@ public:
options_string = options.c_str();
}
- cl_int ret = clCompileProgram(
- m_program, 0, 0, options_string, 0, 0, 0, 0, 0
- );
+ cl_int ret;
+ if (headers.empty())
+ {
+ ret = clCompileProgram(
+ m_program, 0, 0, options_string, 0, 0, 0, 0, 0
+ );
+ }
+ else
+ {
+ std::vector<const char*> header_names(headers.size());
+ std::vector<cl_program> header_programs(headers.size());
+ for (size_t i = 0; i < headers.size(); ++i)
+ {
+ header_names[i] = headers[i].first.c_str();
+ header_programs[i] = headers[i].second.m_program;
+ }
+
+ ret = clCompileProgram(
+ m_program,
+ 0,
+ 0,
+ options_string,
+ static_cast<cl_uint>(headers.size()),
+ header_programs.data(),
+ header_names.data(),
+ 0,
+ 0
+ );
+ }
+
if(ret != CL_SUCCESS){
BOOST_THROW_EXCEPTION(opencl_error(ret));
@@ -329,7 +358,7 @@ public:
return program(program_, false);
}
- #endif // CL_VERSION_1_2
+ #endif // BOOST_COMPUTE_CL_VERSION_1_2
/// Returns the build log.
std::string build_log() const
@@ -432,6 +461,33 @@ public:
return create_with_source(source, context);
}
+ /// Creates a new program with \p files in \p context.
+ ///
+ /// \see_opencl_ref{clCreateProgramWithSource}
+ static program create_with_source_file(const std::vector<std::string> &files,
+ const context &context)
+ {
+ std::vector<std::string> sources(files.size());
+
+ for(size_t i = 0; i < files.size(); ++i) {
+ // open file stream
+ std::ifstream stream(files[i].c_str());
+
+ if(stream.fail()){
+ BOOST_THROW_EXCEPTION(std::ios_base::failure("failed to create stream."));
+ }
+
+ // read source
+ sources[i] = std::string(
+ (std::istreambuf_iterator<char>(stream)),
+ std::istreambuf_iterator<char>()
+ );
+ }
+
+ // create program
+ return create_with_source(sources, context);
+ }
+
/// Creates a new program with \p binary of \p binary_size in
/// \p context.
///
@@ -489,7 +545,7 @@ public:
return create_with_binary(&binary[0], binary.size(), context);
}
- #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ #if defined(BOOST_COMPUTE_CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
/// Creates a new program with the built-in kernels listed in
/// \p kernel_names for \p devices in \p context.
///
@@ -516,7 +572,7 @@ public:
return program(program_, false);
}
- #endif // CL_VERSION_1_2
+ #endif // BOOST_COMPUTE_CL_VERSION_1_2
/// Create a new program with \p source in \p context and builds it with \p options.
/**
@@ -543,10 +599,11 @@ public:
.process( options )
.process( source )
;
+ std::string hash_string = hash;
// Try to get cached program binaries:
try {
- boost::optional<program> prog = load_program_binary(hash, context);
+ boost::optional<program> prog = load_program_binary(hash_string, context);
if (prog) {
prog->build(options);
@@ -575,7 +632,7 @@ public:
#ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE
// Save program binaries for future reuse.
- save_program_binary(hash, prog);
+ save_program_binary(hash_string, prog);
#endif
return prog;
@@ -637,12 +694,12 @@ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(program,
((std::vector<unsigned char *>, CL_PROGRAM_BINARIES))
)
-#ifdef CL_VERSION_1_2
+#ifdef BOOST_COMPUTE_CL_VERSION_1_2
BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(program,
((size_t, CL_PROGRAM_NUM_KERNELS))
((std::string, CL_PROGRAM_KERNEL_NAMES))
)
-#endif // CL_VERSION_1_2
+#endif // BOOST_COMPUTE_CL_VERSION_1_2
} // end compute namespace
} // end boost namespace
diff --git a/boost/compute/svm.hpp b/boost/compute/svm.hpp
index 4bc3a74237..da493a9388 100644
--- a/boost/compute/svm.hpp
+++ b/boost/compute/svm.hpp
@@ -16,7 +16,7 @@
#include <boost/compute/memory/svm_ptr.hpp>
// svm functions require OpenCL 2.0
-#if defined(CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+#if defined(BOOST_COMPUTE_CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
namespace boost {
namespace compute {
@@ -67,6 +67,6 @@ inline void svm_free(const context &context, svm_ptr<T> ptr)
} // end compute namespace
} // end boost namespace
-#endif // CL_VERSION_2_0
+#endif // BOOST_COMPUTE_CL_VERSION_2_0
#endif // BOOST_COMPUTE_PIPE_HPP
diff --git a/boost/compute/system.hpp b/boost/compute/system.hpp
index e6ed353d68..5f29893b9d 100644
--- a/boost/compute/system.hpp
+++ b/boost/compute/system.hpp
@@ -55,6 +55,10 @@ public:
/// name of the platform (e.g. "NVIDIA CUDA")
/// \li \c BOOST_COMPUTE_DEFAULT_VENDOR -
/// name of the device vendor (e.g. "NVIDIA")
+ /// \li \c BOOST_COMPUTE_DEFAULT_ENFORCE -
+ /// If this is set to "1", then throw a no_device_found() exception
+ /// if any of the above environment variables is set, but a matching
+ /// device was not found.
///
/// The default device is determined once on the first time this function
/// is called. Calling this function multiple times will always result in
@@ -220,6 +224,7 @@ private:
const char *type = detail::getenv("BOOST_COMPUTE_DEFAULT_DEVICE_TYPE");
const char *platform = detail::getenv("BOOST_COMPUTE_DEFAULT_PLATFORM");
const char *vendor = detail::getenv("BOOST_COMPUTE_DEFAULT_VENDOR");
+ const char *enforce = detail::getenv("BOOST_COMPUTE_DEFAULT_ENFORCE");
if(name || type || platform || vendor){
for(size_t i = 0; i < devices_.size(); i++){
@@ -243,6 +248,9 @@ private:
return device;
}
+
+ if(enforce && enforce[0] == '1')
+ BOOST_THROW_EXCEPTION(no_device_found());
}
// find the first gpu device
diff --git a/boost/compute/type_traits/type_definition.hpp b/boost/compute/type_traits/type_definition.hpp
index de9095fbd2..3dcc4607fa 100644
--- a/boost/compute/type_traits/type_definition.hpp
+++ b/boost/compute/type_traits/type_definition.hpp
@@ -18,7 +18,10 @@ namespace compute {
namespace detail {
template<class T>
-struct type_definition_trait;
+struct type_definition_trait
+{
+ static std::string value() { return std::string(); }
+};
} // end detail namespace
diff --git a/boost/compute/types/tuple.hpp b/boost/compute/types/tuple.hpp
index 095bd95448..bc2971e49e 100644
--- a/boost/compute/types/tuple.hpp
+++ b/boost/compute/types/tuple.hpp
@@ -206,7 +206,7 @@ inline meta_kernel& operator<<(meta_kernel &kernel, \
typedef typename boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> T; \
BOOST_STATIC_ASSERT(N < size_t(boost::tuples::length<T>::value)); \
kernel.inject_type<T>(); \
- return kernel << expr.m_arg << ".v" << uint_(N); \
+ return kernel << expr.m_arg << ".v" << int_(N); \
}
BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_GET_N, ~)
diff --git a/boost/compute/user_event.hpp b/boost/compute/user_event.hpp
index a3fdba033e..6981b9c7f8 100644
--- a/boost/compute/user_event.hpp
+++ b/boost/compute/user_event.hpp
@@ -17,7 +17,7 @@
namespace boost {
namespace compute {
-#if defined(CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+#if defined(BOOST_COMPUTE_CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
/// \class user_event
/// \brief An user-created event.
///
@@ -80,7 +80,7 @@ public:
}
}
};
-#endif // CL_VERSION_1_1
+#endif // BOOST_COMPUTE_CL_VERSION_1_1
} // end compute namespace
} // end boost namespace
diff --git a/boost/config.hpp b/boost/config.hpp
index d49bb27cd5..f00a980579 100644
--- a/boost/config.hpp
+++ b/boost/config.hpp
@@ -32,7 +32,7 @@
// if we don't have a compiler config set, try and find one:
#if !defined(BOOST_COMPILER_CONFIG) && !defined(BOOST_NO_COMPILER_CONFIG) && !defined(BOOST_NO_CONFIG)
-# include <boost/config/select_compiler_config.hpp>
+# include <boost/config/detail/select_compiler_config.hpp>
#endif
// if we have a compiler config, include it now:
#ifdef BOOST_COMPILER_CONFIG
@@ -41,7 +41,7 @@
// if we don't have a std library config set, try and find one:
#if !defined(BOOST_STDLIB_CONFIG) && !defined(BOOST_NO_STDLIB_CONFIG) && !defined(BOOST_NO_CONFIG) && defined(__cplusplus)
-# include <boost/config/select_stdlib_config.hpp>
+# include <boost/config/detail/select_stdlib_config.hpp>
#endif
// if we have a std library config, include it now:
#ifdef BOOST_STDLIB_CONFIG
@@ -50,7 +50,7 @@
// if we don't have a platform config set, try and find one:
#if !defined(BOOST_PLATFORM_CONFIG) && !defined(BOOST_NO_PLATFORM_CONFIG) && !defined(BOOST_NO_CONFIG)
-# include <boost/config/select_platform_config.hpp>
+# include <boost/config/detail/select_platform_config.hpp>
#endif
// if we have a platform config, include it now:
#ifdef BOOST_PLATFORM_CONFIG
@@ -58,7 +58,7 @@
#endif
// get config suffix code:
-#include <boost/config/suffix.hpp>
+#include <boost/config/detail/suffix.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
diff --git a/boost/config/compiler/borland.hpp b/boost/config/compiler/borland.hpp
index b749496e38..fa891def41 100644
--- a/boost/config/compiler/borland.hpp
+++ b/boost/config/compiler/borland.hpp
@@ -228,6 +228,17 @@
# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
#endif
+// C++17
+#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606)
+# define BOOST_NO_CXX17_STRUCTURED_BINDINGS
+#endif
+#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606)
+# define BOOST_NO_CXX17_INLINE_VARIABLES
+#endif
+#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603)
+# define BOOST_NO_CXX17_FOLD_EXPRESSIONS
+#endif
+
#if __BORLANDC__ >= 0x590
# define BOOST_HAS_TR1_HASH
diff --git a/boost/config/compiler/clang.hpp b/boost/config/compiler/clang.hpp
index 175229c64a..157a94d267 100644
--- a/boost/config/compiler/clang.hpp
+++ b/boost/config/compiler/clang.hpp
@@ -27,6 +27,10 @@
#define __has_attribute(x) 0
#endif
+#ifndef __has_cpp_attribute
+#define __has_cpp_attribute(x) 0
+#endif
+
#if !__has_feature(cxx_exceptions) && !defined(BOOST_NO_EXCEPTIONS)
# define BOOST_NO_EXCEPTIONS
#endif
@@ -282,6 +286,16 @@
# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
#endif
+#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606)
+# define BOOST_NO_CXX17_STRUCTURED_BINDINGS
+#endif
+
+// Clang 3.9+ in c++1z
+#if !__has_cpp_attribute(fallthrough) || __cplusplus < 201406L
+# define BOOST_NO_CXX17_INLINE_VARIABLES
+# define BOOST_NO_CXX17_FOLD_EXPRESSIONS
+#endif
+
#if __cplusplus < 201103L
#define BOOST_NO_CXX11_SFINAE_EXPR
#endif
@@ -296,6 +310,11 @@
#define BOOST_UNREACHABLE_RETURN(x) __builtin_unreachable();
#endif
+#if (__clang_major__ == 3) && (__clang_minor__ == 0)
+// Apparently a clang bug:
+# define BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS
+#endif
+
// Clang has supported the 'unused' attribute since the first release.
#define BOOST_ATTRIBUTE_UNUSED __attribute__((__unused__))
diff --git a/boost/config/compiler/codegear.hpp b/boost/config/compiler/codegear.hpp
index 3c5262fe49..44ca8428e4 100644
--- a/boost/config/compiler/codegear.hpp
+++ b/boost/config/compiler/codegear.hpp
@@ -154,6 +154,19 @@
# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
#endif
+// C++17
+#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606)
+# define BOOST_NO_CXX17_STRUCTURED_BINDINGS
+#endif
+
+#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606)
+# define BOOST_NO_CXX17_INLINE_VARIABLES
+#endif
+
+#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603)
+# define BOOST_NO_CXX17_FOLD_EXPRESSIONS
+#endif
+
//
// TR1 macros:
//
diff --git a/boost/config/compiler/common_edg.hpp b/boost/config/compiler/common_edg.hpp
index eab9378486..d49ceb68e2 100644
--- a/boost/config/compiler/common_edg.hpp
+++ b/boost/config/compiler/common_edg.hpp
@@ -138,6 +138,17 @@
# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
#endif
+// C++17
+#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606)
+# define BOOST_NO_CXX17_STRUCTURED_BINDINGS
+#endif
+#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606)
+# define BOOST_NO_CXX17_INLINE_VARIABLES
+#endif
+#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603)
+# define BOOST_NO_CXX17_FOLD_EXPRESSIONS
+#endif
+
#ifdef c_plusplus
// EDG has "long long" in non-strict mode
// However, some libraries have insufficient "long long" support
diff --git a/boost/config/compiler/diab.hpp b/boost/config/compiler/diab.hpp
new file mode 100644
index 0000000000..0de72d06aa
--- /dev/null
+++ b/boost/config/compiler/diab.hpp
@@ -0,0 +1,19 @@
+// (C) Copyright Brian Kuhl 2016.
+// 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)
+
+// Check this is a recent EDG based compiler, otherwise we don't support it here:
+
+
+#ifndef __EDG_VERSION__
+# error "Unknown Diab compiler version - please run the configure tests and report the results"
+#endif
+
+#include "boost/config/compiler/common_edg.hpp"
+
+#define BOOST_HAS_LONG_LONG
+#define BOOST_NO_TWO_PHASE_NAME_LOOKUP
+#define BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+#define BOOST_NO_CXX11_HDR_CODECVT
+#define BOOST_COMPILER "Wind River Diab " BOOST_STRINGIZE(__VERSION_NUMBER__)
diff --git a/boost/config/compiler/digitalmars.hpp b/boost/config/compiler/digitalmars.hpp
index e371a68e99..e4c5afddd2 100644
--- a/boost/config/compiler/digitalmars.hpp
+++ b/boost/config/compiler/digitalmars.hpp
@@ -114,6 +114,17 @@
# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
#endif
+// C++17
+#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606)
+# define BOOST_NO_CXX17_STRUCTURED_BINDINGS
+#endif
+#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606)
+# define BOOST_NO_CXX17_INLINE_VARIABLES
+#endif
+#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603)
+# define BOOST_NO_CXX17_FOLD_EXPRESSIONS
+#endif
+
#if (__DMC__ <= 0x840)
#error "Compiler not supported or configured - please reconfigure"
#endif
diff --git a/boost/config/compiler/gcc.hpp b/boost/config/compiler/gcc.hpp
index c82cbc7eda..d1cfed7a32 100644
--- a/boost/config/compiler/gcc.hpp
+++ b/boost/config/compiler/gcc.hpp
@@ -288,6 +288,28 @@
# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
#endif
+// C++17
+#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606)
+# define BOOST_NO_CXX17_STRUCTURED_BINDINGS
+#endif
+#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606)
+# define BOOST_NO_CXX17_INLINE_VARIABLES
+#endif
+#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603)
+# define BOOST_NO_CXX17_FOLD_EXPRESSIONS
+#endif
+
+#if __GNUC__ >= 7
+# define BOOST_FALLTHROUGH __attribute__((fallthrough))
+#endif
+
+#ifdef __MINGW32__
+// Currently (June 2017) thread_local is broken on mingw for all current compiler releases, see
+// https://sourceforge.net/p/mingw-w64/bugs/527/
+// Not setting this causes program termination on thread exit.
+#define BOOST_NO_CXX11_THREAD_LOCAL
+#endif
+
//
// Unused attribute:
#if __GNUC__ >= 4
diff --git a/boost/config/compiler/gcc_xml.hpp b/boost/config/compiler/gcc_xml.hpp
index 63b08ac483..2b47585ab8 100644
--- a/boost/config/compiler/gcc_xml.hpp
+++ b/boost/config/compiler/gcc_xml.hpp
@@ -92,6 +92,17 @@
# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
#endif
+// C++17
+#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606)
+# define BOOST_NO_CXX17_STRUCTURED_BINDINGS
+#endif
+#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606)
+# define BOOST_NO_CXX17_INLINE_VARIABLES
+#endif
+#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603)
+# define BOOST_NO_CXX17_FOLD_EXPRESSIONS
+#endif
+
#define BOOST_COMPILER "GCC-XML C++ version " __GCCXML__
diff --git a/boost/config/compiler/metrowerks.hpp b/boost/config/compiler/metrowerks.hpp
index 8d42563c34..99ff0f5eea 100644
--- a/boost/config/compiler/metrowerks.hpp
+++ b/boost/config/compiler/metrowerks.hpp
@@ -157,6 +157,17 @@
# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
#endif
+// C++17
+#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606)
+# define BOOST_NO_CXX17_STRUCTURED_BINDINGS
+#endif
+#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606)
+# define BOOST_NO_CXX17_INLINE_VARIABLES
+#endif
+#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603)
+# define BOOST_NO_CXX17_FOLD_EXPRESSIONS
+#endif
+
#define BOOST_COMPILER "Metrowerks CodeWarrior C++ version " BOOST_STRINGIZE(BOOST_COMPILER_VERSION)
//
diff --git a/boost/config/compiler/mpw.hpp b/boost/config/compiler/mpw.hpp
index 1b8d39ea29..d9544345ac 100644
--- a/boost/config/compiler/mpw.hpp
+++ b/boost/config/compiler/mpw.hpp
@@ -106,6 +106,17 @@
# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
#endif
+// C++17
+#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606)
+# define BOOST_NO_CXX17_STRUCTURED_BINDINGS
+#endif
+#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606)
+# define BOOST_NO_CXX17_INLINE_VARIABLES
+#endif
+#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603)
+# define BOOST_NO_CXX17_FOLD_EXPRESSIONS
+#endif
+
//
// versions check:
// we don't support MPW prior to version 8.9:
diff --git a/boost/config/compiler/nvcc.hpp b/boost/config/compiler/nvcc.hpp
index b31d4f4fa4..43039b5c25 100644
--- a/boost/config/compiler/nvcc.hpp
+++ b/boost/config/compiler/nvcc.hpp
@@ -30,3 +30,22 @@
#if defined(_MSC_VER)
# define BOOST_NO_CXX11_CONSTEXPR
#endif
+
+#ifdef __CUDACC__
+//
+// When compiing .cu files, there's a bunch of stuff that doesn't work with msvc:
+//
+#if defined(_MSC_VER)
+# define BOOST_NO_CXX14_DIGIT_SEPARATORS
+# define BOOST_NO_CXX11_UNICODE_LITERALS
+#endif
+//
+// And this one effects the NVCC front end,
+// See https://svn.boost.org/trac/boost/ticket/13049
+//
+#if (__CUDACC_VER__ >= 80000) && (__CUDACC_VER__ < 80100)
+# define BOOST_NO_CXX11_NOEXCEPT
+#endif
+
+#endif
+
diff --git a/boost/config/compiler/pathscale.hpp b/boost/config/compiler/pathscale.hpp
index 016ad5a42f..94b3f91d07 100644
--- a/boost/config/compiler/pathscale.hpp
+++ b/boost/config/compiler/pathscale.hpp
@@ -12,7 +12,12 @@
# define BOOST_COMPILER "PathScale EKOPath C++ Compiler version " __PATHSCALE__
#endif
-#if __PATHCC__ >= 4
+#if __PATHCC__ >= 6
+// PathCC is based on clang, and supports the __has_*() builtins used
+// to detect features in clang.hpp. Since the clang toolset is much
+// better maintained, it is more convenient to reuse its definitions.
+# include "boost/config/compiler/clang.hpp"
+#elif __PATHCC__ >= 4
# define BOOST_MSVC6_MEMBER_TEMPLATES
# define BOOST_HAS_UNISTD_H
# define BOOST_HAS_STDINT_H
@@ -113,4 +118,15 @@
#if !defined(__cpp_variable_templates) || (__cpp_variable_templates < 201304)
# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
#endif
+
+// C++17
+#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606)
+# define BOOST_NO_CXX17_STRUCTURED_BINDINGS
+#endif
+#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606)
+# define BOOST_NO_CXX17_INLINE_VARIABLES
+#endif
+#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603)
+# define BOOST_NO_CXX17_FOLD_EXPRESSIONS
+#endif
#endif
diff --git a/boost/config/compiler/pgi.hpp b/boost/config/compiler/pgi.hpp
index af7005142f..4c402ba0d6 100644
--- a/boost/config/compiler/pgi.hpp
+++ b/boost/config/compiler/pgi.hpp
@@ -151,6 +151,17 @@
#if !defined(__cpp_variable_templates) || (__cpp_variable_templates < 201304)
# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
#endif
+
+// C++17
+#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606)
+# define BOOST_NO_CXX17_STRUCTURED_BINDINGS
+#endif
+#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606)
+# define BOOST_NO_CXX17_INLINE_VARIABLES
+#endif
+#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603)
+# define BOOST_NO_CXX17_FOLD_EXPRESSIONS
+#endif
//
// version check:
// probably nothing to do here?
diff --git a/boost/config/compiler/sunpro_cc.hpp b/boost/config/compiler/sunpro_cc.hpp
index cdd30b14ea..2453e7cfc1 100644
--- a/boost/config/compiler/sunpro_cc.hpp
+++ b/boost/config/compiler/sunpro_cc.hpp
@@ -172,6 +172,17 @@
# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
#endif
+// C++17
+#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606)
+# define BOOST_NO_CXX17_STRUCTURED_BINDINGS
+#endif
+#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606)
+# define BOOST_NO_CXX17_INLINE_VARIABLES
+#endif
+#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603)
+# define BOOST_NO_CXX17_FOLD_EXPRESSIONS
+#endif
+
// Turn on threading support for Solaris 12.
// Ticket #11972
#if (__SUNPRO_CC >= 0x5140) && defined(__SunOS_5_12) && !defined(BOOST_HAS_THREADS)
diff --git a/boost/config/compiler/vacpp.hpp b/boost/config/compiler/vacpp.hpp
index b75a1bd144..683c167dbf 100644
--- a/boost/config/compiler/vacpp.hpp
+++ b/boost/config/compiler/vacpp.hpp
@@ -162,3 +162,14 @@
#if !defined(__cpp_variable_templates) || (__cpp_variable_templates < 201304)
# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
#endif
+
+// C++17
+#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606)
+# define BOOST_NO_CXX17_STRUCTURED_BINDINGS
+#endif
+#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606)
+# define BOOST_NO_CXX17_INLINE_VARIABLES
+#endif
+#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603)
+# define BOOST_NO_CXX17_FOLD_EXPRESSIONS
+#endif
diff --git a/boost/config/compiler/visualc.hpp b/boost/config/compiler/visualc.hpp
index 760e2833f8..c0557de712 100644
--- a/boost/config/compiler/visualc.hpp
+++ b/boost/config/compiler/visualc.hpp
@@ -107,7 +107,7 @@
//
// TR1 features:
//
-#if _MSC_VER >= 1700
+#if (_MSC_VER >= 1700) && defined(_HAS_CXX17) && (_HAS_CXX17 > 0)
// # define BOOST_HAS_TR1_HASH // don't know if this is true yet.
// # define BOOST_HAS_TR1_TYPE_TRAITS // don't know if this is true yet.
# define BOOST_HAS_TR1_UNORDERED_MAP
@@ -194,7 +194,6 @@
//
#if (_MSC_VER < 1910)
# define BOOST_NO_CXX14_AGGREGATE_NSDMI
-# define BOOST_NO_CXX14_CONSTEXPR
#endif
// MSVC including version 14 has not yet completely
@@ -218,6 +217,12 @@
//
#define BOOST_NO_TWO_PHASE_NAME_LOOKUP
#define BOOST_NO_CXX11_SFINAE_EXPR
+// C++ 14:
+# define BOOST_NO_CXX14_CONSTEXPR
+// C++ 17:
+#define BOOST_NO_CXX17_STRUCTURED_BINDINGS
+#define BOOST_NO_CXX17_INLINE_VARIABLES
+#define BOOST_NO_CXX17_FOLD_EXPRESSIONS
//
// Things that don't work in clr mode:
diff --git a/boost/config/compiler/xlcpp.hpp b/boost/config/compiler/xlcpp.hpp
index 2aaafc3b66..b267f49bad 100644
--- a/boost/config/compiler/xlcpp.hpp
+++ b/boost/config/compiler/xlcpp.hpp
@@ -23,6 +23,10 @@
#define __has_extension __has_feature
#endif
+#ifndef __has_cpp_attribute
+#define __has_cpp_attribute(x) 0
+#endif
+
#if !__has_feature(cxx_exceptions) && !defined(BOOST_NO_EXCEPTIONS)
# define BOOST_NO_EXCEPTIONS
#endif
@@ -238,6 +242,16 @@
# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
#endif
+#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606)
+# define BOOST_NO_CXX17_STRUCTURED_BINDINGS
+#endif
+
+// Clang 3.9+ in c++1z
+#if !__has_cpp_attribute(fallthrough) || __cplusplus < 201406L
+# define BOOST_NO_CXX17_INLINE_VARIABLES
+# define BOOST_NO_CXX17_FOLD_EXPRESSIONS
+#endif
+
#if !__has_feature(cxx_thread_local)
# define BOOST_NO_CXX11_THREAD_LOCAL
#endif
diff --git a/boost/config/compiler/xlcpp_zos.hpp b/boost/config/compiler/xlcpp_zos.hpp
new file mode 100644
index 0000000000..c554903a0b
--- /dev/null
+++ b/boost/config/compiler/xlcpp_zos.hpp
@@ -0,0 +1,168 @@
+// Copyright (c) 2017 Dynatrace
+//
+// Distributed under the 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.
+
+// Compiler setup for IBM z/OS XL C/C++ compiler.
+
+// Oldest compiler version currently supported is 2.1 (V2R1)
+#if !defined(__IBMCPP__) || !defined(__COMPILER_VER__) || __COMPILER_VER__ < 0x42010000
+# error "Compiler not supported or configured - please reconfigure"
+#endif
+
+#if __COMPILER_VER__ > 0x42010000
+# if defined(BOOST_ASSERT_CONFIG)
+# error "Unknown compiler version - please run the configure tests and report the results"
+# endif
+#endif
+
+#define BOOST_COMPILER "IBM z/OS XL C/C++ version " BOOST_STRINGIZE(__COMPILER_VER__)
+#define BOOST_XLCPP_ZOS __COMPILER_VER__
+
+// -------------------------------------
+
+#include <features.h> // For __UU, __C99, __TR1, ...
+
+#if !defined(__IBMCPP_DEFAULTED_AND_DELETED_FUNCTIONS)
+# define BOOST_NO_CXX11_DELETED_FUNCTIONS
+# define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
+# define BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS
+#endif
+
+// -------------------------------------
+
+#if defined(__UU) || defined(__C99) || defined(__TR1)
+# define BOOST_HAS_LOG1P
+# define BOOST_HAS_EXPM1
+#endif
+
+#if defined(__C99) || defined(__TR1)
+# define BOOST_HAS_STDINT_H
+#else
+# define BOOST_NO_FENV_H
+#endif
+
+// -------------------------------------
+
+#define BOOST_HAS_NRVO
+
+#if !defined(__RTTI_ALL__)
+# define BOOST_NO_RTTI
+#endif
+
+#if !defined(_CPPUNWIND) && !defined(__EXCEPTIONS)
+# define BOOST_NO_EXCEPTIONS
+#endif
+
+#if defined(_LONG_LONG) || defined(__IBMCPP_C99_LONG_LONG) || defined(__LL)
+# define BOOST_HAS_LONG_LONG
+#else
+# define BOOST_NO_LONG_LONG
+#endif
+
+#if defined(_LONG_LONG) || defined(__IBMCPP_C99_LONG_LONG) || defined(__LL) || defined(_LP64)
+# define BOOST_HAS_MS_INT64
+#endif
+
+#define BOOST_NO_SFINAE_EXPR
+#define BOOST_NO_CXX11_SFINAE_EXPR
+
+#if defined(__IBMCPP_VARIADIC_TEMPLATES)
+# define BOOST_HAS_VARIADIC_TMPL
+#else
+# define BOOST_NO_CXX11_VARIADIC_TEMPLATES
+# define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS
+#endif
+
+#if defined(__IBMCPP_STATIC_ASSERT)
+# define BOOST_HAS_STATIC_ASSERT
+#else
+# define BOOST_NO_CXX11_STATIC_ASSERT
+#endif
+
+#if defined(__IBMCPP_RVALUE_REFERENCES)
+# define BOOST_HAS_RVALUE_REFS
+#else
+# define BOOST_NO_CXX11_RVALUE_REFERENCES
+#endif
+
+#if !defined(__IBMCPP_SCOPED_ENUM)
+# define BOOST_NO_CXX11_SCOPED_ENUMS
+#endif
+
+#define BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS
+#define BOOST_NO_CXX11_TEMPLATE_ALIASES
+#define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS
+
+#if !defined(__IBMCPP_EXPLICIT_CONVERSION_OPERATORS)
+# define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
+#endif
+
+#if !defined(__IBMCPP_DECLTYPE)
+# define BOOST_NO_CXX11_DECLTYPE
+#else
+# define BOOST_HAS_DECLTYPE
+#endif
+#define BOOST_NO_CXX11_DECLTYPE_N3276
+
+#if !defined(__IBMCPP_INLINE_NAMESPACE)
+# define BOOST_NO_CXX11_INLINE_NAMESPACES
+#endif
+
+#if !defined(__IBMCPP_AUTO_TYPEDEDUCTION)
+# define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS
+# define BOOST_NO_CXX11_AUTO_DECLARATIONS
+# define BOOST_NO_CXX11_TRAILING_RESULT_TYPES
+#endif
+
+#if !defined(__IBM_CHAR32_T__)
+# define BOOST_NO_CXX11_CHAR32_T
+#endif
+#if !defined(__IBM_CHAR16_T__)
+# define BOOST_NO_CXX11_CHAR16_T
+#endif
+
+#if !defined(__IBMCPP_CONSTEXPR)
+# define BOOST_NO_CXX11_CONSTEXPR
+#endif
+
+#define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
+#define BOOST_NO_CXX11_UNICODE_LITERALS
+#define BOOST_NO_CXX11_RAW_LITERALS
+#define BOOST_NO_CXX11_RANGE_BASED_FOR
+#define BOOST_NO_CXX11_NULLPTR
+#define BOOST_NO_CXX11_NOEXCEPT
+#define BOOST_NO_CXX11_LAMBDAS
+#define BOOST_NO_CXX11_USER_DEFINED_LITERALS
+#define BOOST_NO_CXX11_THREAD_LOCAL
+#define BOOST_NO_CXX11_REF_QUALIFIERS
+#define BOOST_NO_CXX11_FINAL
+#define BOOST_NO_CXX11_ALIGNAS
+#define BOOST_NO_CXX14_VARIABLE_TEMPLATES
+#define BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION
+#define BOOST_NO_CXX14_AGGREGATE_NSDMI
+#define BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES
+#define BOOST_NO_CXX14_GENERIC_LAMBDAS
+#define BOOST_NO_CXX14_DIGIT_SEPARATORS
+#define BOOST_NO_CXX14_DECLTYPE_AUTO
+#define BOOST_NO_CXX14_CONSTEXPR
+#define BOOST_NO_CXX14_BINARY_LITERALS
+#define BOOST_NO_CXX17_STRUCTURED_BINDINGS
+#define BOOST_NO_CXX17_INLINE_VARIABLES
+#define BOOST_NO_CXX17_FOLD_EXPRESSIONS
+
+// -------------------------------------
+
+#if defined(__IBM_ATTRIBUTES)
+# define BOOST_FORCEINLINE inline __attribute__ ((__always_inline__))
+# define BOOST_NOINLINE __attribute__ ((__noinline__))
+// No BOOST_ALIGNMENT - explicit alignment support is broken (V2R1).
+#endif
+
+extern "builtin" long __builtin_expect(long, long);
+
+#define BOOST_LIKELY(x) __builtin_expect((x) && true, 1)
+#define BOOST_UNLIKELY(x) __builtin_expect((x) && true, 0)
diff --git a/boost/config/posix_features.hpp b/boost/config/detail/posix_features.hpp
index d12954797f..d12954797f 100644
--- a/boost/config/posix_features.hpp
+++ b/boost/config/detail/posix_features.hpp
diff --git a/boost/config/select_compiler_config.hpp b/boost/config/detail/select_compiler_config.hpp
index 7a75708428..97d47c1c56 100644
--- a/boost/config/select_compiler_config.hpp
+++ b/boost/config/detail/select_compiler_config.hpp
@@ -48,6 +48,10 @@
// Digital Mars C++
# define BOOST_COMPILER_CONFIG "boost/config/compiler/digitalmars.hpp"
+#elif defined __DCC__
+// Wind River Diab C++
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/diab.hpp"
+
# elif defined(__GNUC__) && !defined(__ibmxl__)
// GNU C++:
# define BOOST_COMPILER_CONFIG "boost/config/compiler/gcc.hpp"
@@ -92,8 +96,12 @@
// MPW MrCpp or SCpp
# define BOOST_COMPILER_CONFIG "boost/config/compiler/mpw.hpp"
+#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) && defined(__MVS__)
+// IBM z/OS XL C/C++
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/xlcpp_zos.hpp"
+
#elif defined(__ibmxl__)
-// IBM XL C/C++ for Linux (Little Endian)
+// IBM XL C/C++ for Linux (Little Endian)
# define BOOST_COMPILER_CONFIG "boost/config/compiler/xlcpp.hpp"
#elif defined(__IBMCPP__)
@@ -140,6 +148,8 @@
#include <boost/config/compiler/sunpro_cc.hpp>
#include <boost/config/compiler/hp_acc.hpp>
#include <boost/config/compiler/mpw.hpp>
+#include <boost/config/compiler/xlcpp_zos.hpp>
+#include <boost/config/compiler/xlcpp.hpp>
#include <boost/config/compiler/vacpp.hpp>
#include <boost/config/compiler/pgi.hpp>
#include <boost/config/compiler/visualc.hpp>
diff --git a/boost/config/select_platform_config.hpp b/boost/config/detail/select_platform_config.hpp
index 62fd818b93..b36eca57a2 100644
--- a/boost/config/select_platform_config.hpp
+++ b/boost/config/detail/select_platform_config.hpp
@@ -53,8 +53,12 @@
// MacOS
# define BOOST_PLATFORM_CONFIG "boost/config/platform/macos.hpp"
+#elif defined(__TOS_MVS__)
+// IBM z/OS
+# define BOOST_PLATFORM_CONFIG "boost/config/platform/zos.hpp"
+
#elif defined(__IBMCPP__) || defined(_AIX)
-// IBM
+// IBM AIX
# define BOOST_PLATFORM_CONFIG "boost/config/platform/aix.hpp"
#elif defined(__amigaos__)
@@ -97,7 +101,7 @@
# define BOOST_HAS_UNISTD_H
# endif
-# include <boost/config/posix_features.hpp>
+# include <boost/config/detail/posix_features.hpp>
# endif
@@ -122,6 +126,7 @@
# include "boost/config/platform/win32.hpp"
# include "boost/config/platform/beos.hpp"
# include "boost/config/platform/macos.hpp"
+# include "boost/config/platform/zos.hpp"
# include "boost/config/platform/aix.hpp"
# include "boost/config/platform/amigaos.hpp"
# include "boost/config/platform/qnxnto.hpp"
@@ -129,7 +134,7 @@
# include "boost/config/platform/symbian.hpp"
# include "boost/config/platform/cray.hpp"
# include "boost/config/platform/vms.hpp"
-# include <boost/config/posix_features.hpp>
+# include <boost/config/detail/posix_features.hpp>
diff --git a/boost/config/select_stdlib_config.hpp b/boost/config/detail/select_stdlib_config.hpp
index e270a8813a..8db778c86b 100644
--- a/boost/config/select_stdlib_config.hpp
+++ b/boost/config/detail/select_stdlib_config.hpp
@@ -66,6 +66,10 @@
// MSL standard lib:
# define BOOST_STDLIB_CONFIG "boost/config/stdlib/msl.hpp"
+#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) && defined(__MVS__)
+// IBM z/OS XL C/C++
+# define BOOST_STDLIB_CONFIG "boost/config/stdlib/xlcpp_zos.hpp"
+
#elif defined(__IBMCPP__)
// take the default VACPP std lib
# define BOOST_STDLIB_CONFIG "boost/config/stdlib/vacpp.hpp"
@@ -98,6 +102,7 @@
# include "boost/config/stdlib/libstdcpp3.hpp"
# include "boost/config/stdlib/sgi.hpp"
# include "boost/config/stdlib/msl.hpp"
+# include "boost/config/stdlib/xlcpp_zos.hpp"
# include "boost/config/stdlib/vacpp.hpp"
# include "boost/config/stdlib/modena.hpp"
# include "boost/config/stdlib/dinkumware.hpp"
diff --git a/boost/config/suffix.hpp b/boost/config/detail/suffix.hpp
index 6df9223fb2..6abec22f58 100644
--- a/boost/config/suffix.hpp
+++ b/boost/config/detail/suffix.hpp
@@ -643,7 +643,7 @@ namespace std{ using ::type_info; }
# define BOOST_NORETURN __declspec(noreturn)
# elif defined(__GNUC__)
# define BOOST_NORETURN __attribute__ ((__noreturn__))
-# elif defined(__has_attribute) && defined(__SUNPRO_CC)
+# elif defined(__has_attribute) && defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x5130)
# if __has_attribute(noreturn)
# define BOOST_NORETURN [[noreturn]]
# endif
@@ -676,15 +676,17 @@ namespace std{ using ::type_info; }
// Type and data alignment specification
//
-#if !defined(BOOST_NO_CXX11_ALIGNAS)
-# define BOOST_ALIGNMENT(x) alignas(x)
-#elif defined(_MSC_VER)
-# define BOOST_ALIGNMENT(x) __declspec(align(x))
-#elif defined(__GNUC__)
-# define BOOST_ALIGNMENT(x) __attribute__ ((__aligned__(x)))
-#else
-# define BOOST_NO_ALIGNMENT
-# define BOOST_ALIGNMENT(x)
+#if !defined(BOOST_ALIGNMENT)
+# if !defined(BOOST_NO_CXX11_ALIGNAS)
+# define BOOST_ALIGNMENT(x) alignas(x)
+# elif defined(_MSC_VER)
+# define BOOST_ALIGNMENT(x) __declspec(align(x))
+# elif defined(__GNUC__)
+# define BOOST_ALIGNMENT(x) __attribute__ ((__aligned__(x)))
+# else
+# define BOOST_NO_ALIGNMENT
+# define BOOST_ALIGNMENT(x)
+# endif
#endif
// Lack of non-public defaulted functions is implied by the lack of any defaulted functions
diff --git a/boost/config/platform/aix.hpp b/boost/config/platform/aix.hpp
index 894ef42ce9..a48e232061 100644
--- a/boost/config/platform/aix.hpp
+++ b/boost/config/platform/aix.hpp
@@ -26,7 +26,7 @@
//#define BOOST_HAS_PTHREAD_YIELD
// boilerplate code:
-#include <boost/config/posix_features.hpp>
+#include <boost/config/detail/posix_features.hpp>
diff --git a/boost/config/platform/beos.hpp b/boost/config/platform/beos.hpp
index 48c3d8dc5b..6158c1c20b 100644
--- a/boost/config/platform/beos.hpp
+++ b/boost/config/platform/beos.hpp
@@ -20,7 +20,7 @@
#endif
// boilerplate code:
-#include <boost/config/posix_features.hpp>
+#include <boost/config/detail/posix_features.hpp>
diff --git a/boost/config/platform/bsd.hpp b/boost/config/platform/bsd.hpp
index a0142978eb..79e74a080a 100644
--- a/boost/config/platform/bsd.hpp
+++ b/boost/config/platform/bsd.hpp
@@ -77,7 +77,7 @@
// boilerplate code:
#define BOOST_HAS_UNISTD_H
-#include <boost/config/posix_features.hpp>
+#include <boost/config/detail/posix_features.hpp>
diff --git a/boost/config/platform/cray.hpp b/boost/config/platform/cray.hpp
index 5c476e4160..103e9c0620 100644
--- a/boost/config/platform/cray.hpp
+++ b/boost/config/platform/cray.hpp
@@ -12,7 +12,7 @@
// boilerplate code:
#define BOOST_HAS_UNISTD_H
-#include <boost/config/posix_features.hpp>
+#include <boost/config/detail/posix_features.hpp>
diff --git a/boost/config/platform/cygwin.hpp b/boost/config/platform/cygwin.hpp
index 53e23f7f08..8ecc4a4af5 100644
--- a/boost/config/platform/cygwin.hpp
+++ b/boost/config/platform/cygwin.hpp
@@ -43,7 +43,7 @@
#define BOOST_NO_FENV_H
// boilerplate code:
-#include <boost/config/posix_features.hpp>
+#include <boost/config/detail/posix_features.hpp>
//
// Cygwin lies about XSI conformance, there is no nl_types.h:
diff --git a/boost/config/platform/haiku.hpp b/boost/config/platform/haiku.hpp
index 750866c47d..04244c5677 100644
--- a/boost/config/platform/haiku.hpp
+++ b/boost/config/platform/haiku.hpp
@@ -28,4 +28,4 @@
#define BOOST_HAS_GETTIMEOFDAY
// boilerplate code:
-#include <boost/config/posix_features.hpp>
+#include <boost/config/detail/posix_features.hpp>
diff --git a/boost/config/platform/hpux.hpp b/boost/config/platform/hpux.hpp
index 19ce68e597..222622e7ee 100644
--- a/boost/config/platform/hpux.hpp
+++ b/boost/config/platform/hpux.hpp
@@ -43,7 +43,7 @@
// boilerplate code:
#define BOOST_HAS_UNISTD_H
-#include <boost/config/posix_features.hpp>
+#include <boost/config/detail/posix_features.hpp>
// the following are always available:
#ifndef BOOST_HAS_GETTIMEOFDAY
diff --git a/boost/config/platform/irix.hpp b/boost/config/platform/irix.hpp
index aeae49c8b4..0acb651552 100644
--- a/boost/config/platform/irix.hpp
+++ b/boost/config/platform/irix.hpp
@@ -25,7 +25,7 @@
// boilerplate code:
#define BOOST_HAS_UNISTD_H
-#include <boost/config/posix_features.hpp>
+#include <boost/config/detail/posix_features.hpp>
diff --git a/boost/config/platform/linux.hpp b/boost/config/platform/linux.hpp
index 8c43c7b6d3..c4eef8f80c 100644
--- a/boost/config/platform/linux.hpp
+++ b/boost/config/platform/linux.hpp
@@ -24,8 +24,9 @@
#if defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1)))
// <stdint.h> defines int64_t unconditionally, but <sys/types.h> defines
// int64_t only if __GNUC__. Thus, assume a fully usable <stdint.h>
- // only when using GCC.
-# if defined __GNUC__
+ // only when using GCC. Update 2017: this appears not to be the case for
+ // recent glibc releases, see bug report: https://svn.boost.org/trac/boost/ticket/13045
+# if defined(__GNUC__) || ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 5)))
# define BOOST_HAS_STDINT_H
# endif
#endif
@@ -71,7 +72,7 @@
// boilerplate code:
#define BOOST_HAS_UNISTD_H
-#include <boost/config/posix_features.hpp>
+#include <boost/config/detail/posix_features.hpp>
#if defined(__USE_GNU) && !defined(__ANDROID__) && !defined(ANDROID)
#define BOOST_HAS_PTHREAD_YIELD
#endif
diff --git a/boost/config/platform/macos.hpp b/boost/config/platform/macos.hpp
index 5be4e3b3da..ed7dc15f28 100644
--- a/boost/config/platform/macos.hpp
+++ b/boost/config/platform/macos.hpp
@@ -25,7 +25,7 @@
// to replace the platform-native BSD one. G++ users
// should also always be able to do this on MaxOS X.
//
-# include <boost/config/posix_features.hpp>
+# include <boost/config/detail/posix_features.hpp>
# ifndef BOOST_HAS_STDINT_H
# define BOOST_HAS_STDINT_H
# endif
diff --git a/boost/config/platform/qnxnto.hpp b/boost/config/platform/qnxnto.hpp
index b1377c8d2c..d0298cb4ec 100644
--- a/boost/config/platform/qnxnto.hpp
+++ b/boost/config/platform/qnxnto.hpp
@@ -10,7 +10,7 @@
#define BOOST_PLATFORM "QNX"
#define BOOST_HAS_UNISTD_H
-#include <boost/config/posix_features.hpp>
+#include <boost/config/detail/posix_features.hpp>
// QNX claims XOpen version 5 compatibility, but doesn't have an nl_types.h
// or log1p and expm1:
diff --git a/boost/config/platform/solaris.hpp b/boost/config/platform/solaris.hpp
index 6e4efc9e56..51ffe67f33 100644
--- a/boost/config/platform/solaris.hpp
+++ b/boost/config/platform/solaris.hpp
@@ -14,7 +14,7 @@
// boilerplate code:
#define BOOST_HAS_UNISTD_H
-#include <boost/config/posix_features.hpp>
+#include <boost/config/detail/posix_features.hpp>
//
// pthreads don't actually work with gcc unless _PTHREADS is defined:
diff --git a/boost/config/platform/symbian.hpp b/boost/config/platform/symbian.hpp
index e02a7782de..f814d00b5b 100644
--- a/boost/config/platform/symbian.hpp
+++ b/boost/config/platform/symbian.hpp
@@ -24,7 +24,7 @@
#include <stdlib.h>
#endif// boilerplate code:
# define BOOST_HAS_UNISTD_H
-# include <boost/config/posix_features.hpp>
+# include <boost/config/detail/posix_features.hpp>
// S60 SDK defines _POSIX_VERSION as POSIX.1
# ifndef BOOST_HAS_STDINT_H
# define BOOST_HAS_STDINT_H
diff --git a/boost/config/platform/vxworks.hpp b/boost/config/platform/vxworks.hpp
index cdda0158ad..a7f571c499 100644
--- a/boost/config/platform/vxworks.hpp
+++ b/boost/config/platform/vxworks.hpp
@@ -180,7 +180,7 @@
// Luckily, at the moment there seems to be none!
#endif
-// These #defines allow posix_features to work, since vxWorks doesn't
+// These #defines allow detail/posix_features to work, since vxWorks doesn't
// #define them itself for DKMs (for RTPs on the contrary it does):
#ifdef _WRS_KERNEL
# ifndef _POSIX_TIMERS
@@ -286,10 +286,8 @@ inline ssize_t readlink(const char*, char*, size_t){
return -1;
}
-// vxWorks claims to implement gettimeofday in sys/time.h
-// but nevertheless does not provide it! See
-// https://support.windriver.com/olsPortal/faces/maintenance/techtipDetail_noHeader.jspx?docId=16442&contentId=WR_TECHTIP_006256
-// We implement a surrogate version here via clock_gettime:
+#if (_WRS_VXWORKS_MAJOR < 7)
+
inline int gettimeofday(struct timeval *tv, void * /*tzv*/) {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
@@ -297,6 +295,8 @@ inline int gettimeofday(struct timeval *tv, void * /*tzv*/) {
tv->tv_usec = ts.tv_nsec / 1000;
return 0;
}
+#endif
+
// vxWorks does provide neither struct tms nor function times()!
// We implement an empty dummy-function, simply setting the user
@@ -327,6 +327,7 @@ inline clock_t times(struct tms *t){
return ticks;
}
+extern void bzero (void *, size_t); // FD_ZERO uses bzero() but doesn't include strings.h
} // extern "C"
// Put the selfmade functions into the std-namespace, just in case
@@ -349,21 +350,43 @@ namespace std {
// Include signal.h which might contain a typo to be corrected here
#include <signal.h>
-#define getpagesize() sysconf(_SC_PAGESIZE) // getpagesize is deprecated anyway!
+inline int getpagesize() { return sysconf(_SC_PAGESIZE); } // getpagesize is deprecated anyway!
#ifndef S_ISSOCK
# define S_ISSOCK(mode) ((mode & S_IFMT) == S_IFSOCK) // Is file a socket?
#endif
-#define lstat(p, b) stat(p, b) // lstat() == stat(), as vxWorks has no symlinks!
+inline int lstat(p, b) { return stat(p, b); } // lstat() == stat(), as vxWorks has no symlinks!
#ifndef FPE_FLTINV
# define FPE_FLTINV (FPE_FLTSUB+1) // vxWorks has no FPE_FLTINV, so define one as a dummy
#endif
#if !defined(BUS_ADRALN) && defined(BUS_ADRALNR)
# define BUS_ADRALN BUS_ADRALNR // Correct a supposed typo in vxWorks' <signal.h>
#endif
-//typedef int locale_t; // locale_t is a POSIX-extension, currently unpresent in vxWorks!
+typedef int locale_t; // locale_t is a POSIX-extension, currently not present in vxWorks!
// #include boilerplate code:
-#include <boost/config/posix_features.hpp>
+#include <boost/config/detail/posix_features.hpp>
// vxWorks lies about XSI conformance, there is no nl_types.h:
#undef BOOST_HAS_NL_TYPES_H
+
+// vxWorks 7 adds C++11 support
+// however it is optional, and does not match exactly the support determined
+// by examining Dinkum STL version and GCC version (or ICC and DCC)
+
+#ifndef _WRS_CONFIG_LANG_LIB_CPLUS_CPLUS_USER_2011
+# define BOOST_NO_CXX11_HDR_ARRAY
+# define BOOST_NO_CXX11_HDR_TYPEINDEX
+# define BOOST_NO_CXX11_HDR_TYPE_TRAITS
+# define BOOST_NO_CXX11_HDR_TUPLE
+# define BOOST_NO_CXX11_ALLOCATOR
+# define BOOST_NO_CXX11_SMART_PTR
+# define BOOST_NO_CXX11_STD_ALIGN
+# define BOOST_NO_CXX11_HDR_UNORDERED_SET
+# define BOOST_NO_CXX11_HDR_TYPE_TRAITS
+# define BOOST_NO_CXX11_HDR_UNORDERED_MAP
+# define BOOST_NO_CXX11_HDR_FUNCTIONAL
+# define BOOST_NO_CXX11_HDR_ATOMIC
+#else
+# define BOOST_NO_CXX11_NULLPTR
+#endif
+
diff --git a/boost/config/platform/zos.hpp b/boost/config/platform/zos.hpp
new file mode 100644
index 0000000000..fa77999edc
--- /dev/null
+++ b/boost/config/platform/zos.hpp
@@ -0,0 +1,32 @@
+// Copyright (c) 2017 Dynatrace
+//
+// Distributed under the 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.
+
+// Platform setup for IBM z/OS.
+
+#define BOOST_PLATFORM "IBM z/OS"
+
+#include <features.h> // For __UU, __C99, __TR1, ...
+
+#if defined(__UU)
+# define BOOST_HAS_GETTIMEOFDAY
+#endif
+
+#if defined(_OPEN_THREADS) || defined(__SUSV3_THR)
+# define BOOST_HAS_PTHREADS
+# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
+# define BOOST_HAS_THREADS
+#endif
+
+#if defined(__SUSV3) || defined(__SUSV3_THR)
+# define BOOST_HAS_SCHED_YIELD
+#endif
+
+#define BOOST_HAS_SIGACTION
+#define BOOST_HAS_UNISTD_H
+#define BOOST_HAS_DIRENT_H
+#define BOOST_HAS_NL_TYPES_H
diff --git a/boost/config/stdlib/dinkumware.hpp b/boost/config/stdlib/dinkumware.hpp
index 3b95dcf3b5..daac5dfb43 100644
--- a/boost/config/stdlib/dinkumware.hpp
+++ b/boost/config/stdlib/dinkumware.hpp
@@ -147,6 +147,13 @@
# define BOOST_NO_CXX11_STD_ALIGN
#endif
+// Before 650 std::pointer_traits has a broken rebind template
+#if !defined(_CPPLIB_VER) || _CPPLIB_VER < 650
+# define BOOST_NO_CXX11_POINTER_TRAITS
+#elif defined(BOOST_MSVC) && BOOST_MSVC < 1910
+# define BOOST_NO_CXX11_POINTER_TRAITS
+#endif
+
#if defined(__has_include)
#if !__has_include(<shared_mutex>)
# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
@@ -163,7 +170,9 @@
#endif
// C++17 features
+#if !defined(_CPPLIB_VER) || (_CPPLIB_VER < 650) || !defined(BOOST_MSVC) || (BOOST_MSVC < 1910) || !defined(_HAS_CXX17) || (_HAS_CXX17 == 0)
# define BOOST_NO_CXX17_STD_APPLY
+#endif
#if !defined(_CPPLIB_VER) || (_CPPLIB_VER < 650)
# define BOOST_NO_CXX17_STD_INVOKE
#endif
@@ -188,11 +197,14 @@
#endif
#if defined(_CPPLIB_VER) && (_CPPLIB_VER >= 650)
-// If _HAS_AUTO_PTR_ETC is defined to 0, std::auto_ptr is not available.
+// If _HAS_AUTO_PTR_ETC is defined to 0, std::auto_ptr and std::random_shuffle are not available.
// See https://www.visualstudio.com/en-us/news/vs2015-vs.aspx#C++
// and http://blogs.msdn.com/b/vcblog/archive/2015/06/19/c-11-14-17-features-in-vs-2015-rtm.aspx
# if defined(_HAS_AUTO_PTR_ETC) && (_HAS_AUTO_PTR_ETC == 0)
# define BOOST_NO_AUTO_PTR
+# define BOOST_NO_CXX98_RANDOM_SHUFFLE
+# define BOOST_NO_CXX98_FUNCTION_BASE
+# define BOOST_NO_CXX98_BINDERS
# endif
#endif
diff --git a/boost/config/stdlib/libcomo.hpp b/boost/config/stdlib/libcomo.hpp
index e3fc627f6f..ce83f082cc 100644
--- a/boost/config/stdlib/libcomo.hpp
+++ b/boost/config/stdlib/libcomo.hpp
@@ -55,6 +55,7 @@
# define BOOST_NO_CXX11_HDR_UNORDERED_SET
# define BOOST_NO_CXX11_NUMERIC_LIMITS
# define BOOST_NO_CXX11_ALLOCATOR
+# define BOOST_NO_CXX11_POINTER_TRAITS
# define BOOST_NO_CXX11_ATOMIC_SMART_PTR
# define BOOST_NO_CXX11_SMART_PTR
# define BOOST_NO_CXX11_HDR_FUNCTIONAL
diff --git a/boost/config/stdlib/libcpp.hpp b/boost/config/stdlib/libcpp.hpp
index 2eea99977d..9c58965f80 100644
--- a/boost/config/stdlib/libcpp.hpp
+++ b/boost/config/stdlib/libcpp.hpp
@@ -29,6 +29,7 @@
// aliases since members rebind_alloc and rebind_traits require it.
#if defined(_LIBCPP_HAS_NO_TEMPLATE_ALIASES)
# define BOOST_NO_CXX11_ALLOCATOR
+# define BOOST_NO_CXX11_POINTER_TRAITS
#endif
#if __cplusplus < 201103
@@ -53,6 +54,7 @@
# define BOOST_NO_CXX11_HDR_UNORDERED_SET
# define BOOST_NO_CXX11_NUMERIC_LIMITS
# define BOOST_NO_CXX11_ALLOCATOR
+# define BOOST_NO_CXX11_POINTER_TRAITS
# define BOOST_NO_CXX11_SMART_PTR
# define BOOST_NO_CXX11_HDR_FUNCTIONAL
# define BOOST_NO_CXX11_STD_ALIGN
@@ -91,6 +93,15 @@
#if (_LIBCPP_VERSION < 4000) || (__cplusplus <= 201402L)
# define BOOST_NO_CXX17_STD_APPLY
#endif
+#if (_LIBCPP_VERSION > 4000) && (__cplusplus > 201402L) && !defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
+# define BOOST_NO_AUTO_PTR
+#endif
+#if (_LIBCPP_VERSION > 4000) && (__cplusplus > 201402L) && !defined(_LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE)
+# define BOOST_NO_CXX98_RANDOM_SHUFFLE
+#endif
+#if (_LIBCPP_VERSION > 4000) && (__cplusplus > 201402L) && !defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS)
+# define BOOST_NO_CXX98_BINDERS
+#endif
#if (_LIBCPP_VERSION <= 1101) && !defined(BOOST_NO_CXX11_THREAD_LOCAL)
// This is a bit of a sledgehammer, because really it's just libc++abi that has no
diff --git a/boost/config/stdlib/libstdcpp3.hpp b/boost/config/stdlib/libstdcpp3.hpp
index 205489a920..9adbc8f171 100644
--- a/boost/config/stdlib/libstdcpp3.hpp
+++ b/boost/config/stdlib/libstdcpp3.hpp
@@ -143,6 +143,37 @@
# define BOOST_LIBSTDCXX_VERSION 40300
#endif
+#if (BOOST_LIBSTDCXX_VERSION < 50100)
+// libstdc++ does not define this function as it's deprecated in C++11, but clang still looks for it,
+// defining it here is a terrible cludge, but should get things working:
+extern "C" char *gets (char *__s);
+#endif
+//
+// clang is unable to parse some GCC headers, add those workarounds here:
+//
+#if BOOST_LIBSTDCXX_VERSION < 50000
+# define BOOST_NO_CXX11_HDR_REGEX
+#endif
+//
+// GCC 4.7.x has no __cxa_thread_atexit which
+// thread_local objects require for cleanup:
+//
+#if BOOST_LIBSTDCXX_VERSION < 40800
+# define BOOST_NO_CXX11_THREAD_LOCAL
+#endif
+//
+// Early clang versions can handle <chrono>, not exactly sure which versions
+// but certainly up to clang-3.8 and gcc-4.6:
+//
+#if (__clang_major__ < 5)
+# if BOOST_LIBSTDCXX_VERSION < 40800
+# define BOOST_NO_CXX11_HDR_FUTURE
+# define BOOST_NO_CXX11_HDR_MUTEX
+# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE
+# define BOOST_NO_CXX11_HDR_CHRONO
+# endif
+#endif
+
//
// GCC 4.8 and 9 add working versions of <atomic> and <regex> respectively.
// However, we have no test for these as the headers were present but broken
@@ -225,6 +256,7 @@
// so 4.7.0 is the first truly conforming one.
# define BOOST_NO_CXX11_HDR_CHRONO
# define BOOST_NO_CXX11_ALLOCATOR
+# define BOOST_NO_CXX11_POINTER_TRAITS
#endif
// C++0x features in GCC 4.8.0 and later
//
diff --git a/boost/config/stdlib/modena.hpp b/boost/config/stdlib/modena.hpp
index fa4a818715..98bdc3fb3e 100644
--- a/boost/config/stdlib/modena.hpp
+++ b/boost/config/stdlib/modena.hpp
@@ -44,6 +44,7 @@
# define BOOST_NO_CXX11_HDR_UNORDERED_SET
# define BOOST_NO_CXX11_NUMERIC_LIMITS
# define BOOST_NO_CXX11_ALLOCATOR
+# define BOOST_NO_CXX11_POINTER_TRAITS
# define BOOST_NO_CXX11_ATOMIC_SMART_PTR
# define BOOST_NO_CXX11_SMART_PTR
# define BOOST_NO_CXX11_HDR_FUNCTIONAL
diff --git a/boost/config/stdlib/msl.hpp b/boost/config/stdlib/msl.hpp
index 8f21a1388d..9606a9aeca 100644
--- a/boost/config/stdlib/msl.hpp
+++ b/boost/config/stdlib/msl.hpp
@@ -34,7 +34,7 @@
# define BOOST_HAS_UNISTD_H
# endif
// boilerplate code:
-# include <boost/config/posix_features.hpp>
+# include <boost/config/detail/posix_features.hpp>
#endif
#if defined(_MWMT) || _MSL_THREADSAFE
@@ -68,6 +68,7 @@
# define BOOST_NO_CXX11_HDR_UNORDERED_SET
# define BOOST_NO_CXX11_NUMERIC_LIMITS
# define BOOST_NO_CXX11_ALLOCATOR
+# define BOOST_NO_CXX11_POINTER_TRAITS
# define BOOST_NO_CXX11_ATOMIC_SMART_PTR
# define BOOST_NO_CXX11_SMART_PTR
# define BOOST_NO_CXX11_HDR_FUNCTIONAL
diff --git a/boost/config/stdlib/roguewave.hpp b/boost/config/stdlib/roguewave.hpp
index 437d38d97c..380d0ff375 100644
--- a/boost/config/stdlib/roguewave.hpp
+++ b/boost/config/stdlib/roguewave.hpp
@@ -180,6 +180,7 @@
# define BOOST_NO_CXX11_HDR_UNORDERED_SET
# define BOOST_NO_CXX11_NUMERIC_LIMITS
# define BOOST_NO_CXX11_ALLOCATOR
+# define BOOST_NO_CXX11_POINTER_TRAITS
# define BOOST_NO_CXX11_ATOMIC_SMART_PTR
# define BOOST_NO_CXX11_SMART_PTR
# define BOOST_NO_CXX11_HDR_FUNCTIONAL
diff --git a/boost/config/stdlib/sgi.hpp b/boost/config/stdlib/sgi.hpp
index 8d2f849f70..5016ff627b 100644
--- a/boost/config/stdlib/sgi.hpp
+++ b/boost/config/stdlib/sgi.hpp
@@ -138,6 +138,7 @@
# define BOOST_NO_CXX11_HDR_UNORDERED_SET
# define BOOST_NO_CXX11_NUMERIC_LIMITS
# define BOOST_NO_CXX11_ALLOCATOR
+# define BOOST_NO_CXX11_POINTER_TRAITS
# define BOOST_NO_CXX11_ATOMIC_SMART_PTR
# define BOOST_NO_CXX11_SMART_PTR
# define BOOST_NO_CXX11_HDR_FUNCTIONAL
diff --git a/boost/config/stdlib/stlport.hpp b/boost/config/stdlib/stlport.hpp
index 518f9efd4a..81e6ccf016 100644
--- a/boost/config/stdlib/stlport.hpp
+++ b/boost/config/stdlib/stlport.hpp
@@ -228,6 +228,7 @@ namespace boost { using std::min; using std::max; }
# define BOOST_NO_CXX11_HDR_UNORDERED_SET
# define BOOST_NO_CXX11_NUMERIC_LIMITS
# define BOOST_NO_CXX11_ALLOCATOR
+# define BOOST_NO_CXX11_POINTER_TRAITS
# define BOOST_NO_CXX11_ATOMIC_SMART_PTR
# define BOOST_NO_CXX11_SMART_PTR
# define BOOST_NO_CXX11_HDR_FUNCTIONAL
diff --git a/boost/config/stdlib/vacpp.hpp b/boost/config/stdlib/vacpp.hpp
index f9afef6387..c159af259f 100644
--- a/boost/config/stdlib/vacpp.hpp
+++ b/boost/config/stdlib/vacpp.hpp
@@ -44,6 +44,7 @@
# define BOOST_NO_CXX11_HDR_UNORDERED_SET
# define BOOST_NO_CXX11_NUMERIC_LIMITS
# define BOOST_NO_CXX11_ALLOCATOR
+# define BOOST_NO_CXX11_POINTER_TRAITS
# define BOOST_NO_CXX11_ATOMIC_SMART_PTR
# define BOOST_NO_CXX11_SMART_PTR
# define BOOST_NO_CXX11_HDR_FUNCTIONAL
diff --git a/boost/config/stdlib/xlcpp_zos.hpp b/boost/config/stdlib/xlcpp_zos.hpp
new file mode 100644
index 0000000000..dce40f5090
--- /dev/null
+++ b/boost/config/stdlib/xlcpp_zos.hpp
@@ -0,0 +1,59 @@
+// Copyright (c) 2017 Dynatrace
+//
+// Distributed under the 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.
+
+// Standard library setup for IBM z/OS XL C/C++ compiler.
+
+// Oldest library version currently supported is 2.1 (V2R1)
+#if __TARGET_LIB__ < 0x42010000
+# error "Library version not supported or configured - please reconfigure"
+#endif
+
+#if __TARGET_LIB__ > 0x42010000
+# if defined(BOOST_ASSERT_CONFIG)
+# error "Unknown library version - please run the configure tests and report the results"
+# endif
+#endif
+
+#define BOOST_STDLIB "IBM z/OS XL C/C++ standard library"
+
+#define BOOST_HAS_MACRO_USE_FACET
+
+#define BOOST_NO_CXX11_HDR_TYPE_TRAITS
+#define BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+
+#define BOOST_NO_CXX11_ADDRESSOF
+#define BOOST_NO_CXX11_SMART_PTR
+#define BOOST_NO_CXX11_ATOMIC_SMART_PTR
+#define BOOST_NO_CXX11_NUMERIC_LIMITS
+#define BOOST_NO_CXX11_ALLOCATOR
+#define BOOST_NO_CXX11_POINTER_TRAITS
+#define BOOST_NO_CXX11_HDR_FUNCTIONAL
+#define BOOST_NO_CXX11_HDR_UNORDERED_SET
+#define BOOST_NO_CXX11_HDR_UNORDERED_MAP
+#define BOOST_NO_CXX11_HDR_TYPEINDEX
+#define BOOST_NO_CXX11_HDR_TUPLE
+#define BOOST_NO_CXX11_HDR_THREAD
+#define BOOST_NO_CXX11_HDR_SYSTEM_ERROR
+#define BOOST_NO_CXX11_HDR_REGEX
+#define BOOST_NO_CXX11_HDR_RATIO
+#define BOOST_NO_CXX11_HDR_RANDOM
+#define BOOST_NO_CXX11_HDR_MUTEX
+#define BOOST_NO_CXX11_HDR_FUTURE
+#define BOOST_NO_CXX11_HDR_FORWARD_LIST
+#define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE
+#define BOOST_NO_CXX11_HDR_CODECVT
+#define BOOST_NO_CXX11_HDR_CHRONO
+#define BOOST_NO_CXX11_HDR_ATOMIC
+#define BOOST_NO_CXX11_HDR_ARRAY
+#define BOOST_NO_CXX11_STD_ALIGN
+
+#define BOOST_NO_CXX14_STD_EXCHANGE
+#define BOOST_NO_CXX14_HDR_SHARED_MUTEX
+
+#define BOOST_NO_CXX17_STD_INVOKE
+#define BOOST_NO_CXX17_STD_APPLY
diff --git a/boost/config/workaround.hpp b/boost/config/workaround.hpp
new file mode 100644
index 0000000000..0ce8108c2e
--- /dev/null
+++ b/boost/config/workaround.hpp
@@ -0,0 +1,277 @@
+// 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)
+#ifndef BOOST_CONFIG_WORKAROUND_HPP
+#define BOOST_CONFIG_WORKAROUND_HPP
+
+// Compiler/library version workaround macro
+//
+// Usage:
+//
+// #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+// // workaround for eVC4 and VC6
+// ... // workaround code here
+// #endif
+//
+// When BOOST_STRICT_CONFIG is defined, expands to 0. Otherwise, the
+// first argument must be undefined or expand to a numeric
+// value. The above expands to:
+//
+// (BOOST_MSVC) != 0 && (BOOST_MSVC) < 1300
+//
+// When used for workarounds that apply to the latest known version
+// and all earlier versions of a compiler, the following convention
+// should be observed:
+//
+// #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1301))
+//
+// The version number in this case corresponds to the last version in
+// which the workaround was known to have been required. When
+// BOOST_DETECT_OUTDATED_WORKAROUNDS is not the defined, the macro
+// BOOST_TESTED_AT(x) expands to "!= 0", which effectively activates
+// the workaround for any version of the compiler. When
+// BOOST_DETECT_OUTDATED_WORKAROUNDS is defined, a compiler warning or
+// error will be issued if the compiler version exceeds the argument
+// to BOOST_TESTED_AT(). This can be used to locate workarounds which
+// may be obsoleted by newer versions.
+
+#ifndef BOOST_STRICT_CONFIG
+
+#include <boost/config.hpp>
+
+#ifndef __BORLANDC__
+#define __BORLANDC___WORKAROUND_GUARD 1
+#else
+#define __BORLANDC___WORKAROUND_GUARD 0
+#endif
+#ifndef __CODEGEARC__
+#define __CODEGEARC___WORKAROUND_GUARD 1
+#else
+#define __CODEGEARC___WORKAROUND_GUARD 0
+#endif
+#ifndef _MSC_VER
+#define _MSC_VER_WORKAROUND_GUARD 1
+#else
+#define _MSC_VER_WORKAROUND_GUARD 0
+#endif
+#ifndef _MSC_FULL_VER
+#define _MSC_FULL_VER_WORKAROUND_GUARD 1
+#else
+#define _MSC_FULL_VER_WORKAROUND_GUARD 0
+#endif
+#ifndef BOOST_MSVC
+#define BOOST_MSVC_WORKAROUND_GUARD 1
+#else
+#define BOOST_MSVC_WORKAROUND_GUARD 0
+#endif
+#ifndef BOOST_MSVC_FULL_VER
+#define BOOST_MSVC_FULL_VER_WORKAROUND_GUARD 1
+#else
+#define BOOST_MSVC_FULL_VER_WORKAROUND_GUARD 0
+#endif
+#ifndef __GNUC__
+#define __GNUC___WORKAROUND_GUARD 1
+#else
+#define __GNUC___WORKAROUND_GUARD 0
+#endif
+#ifndef __GNUC_MINOR__
+#define __GNUC_MINOR___WORKAROUND_GUARD 1
+#else
+#define __GNUC_MINOR___WORKAROUND_GUARD 0
+#endif
+#ifndef __GNUC_PATCHLEVEL__
+#define __GNUC_PATCHLEVEL___WORKAROUND_GUARD 1
+#else
+#define __GNUC_PATCHLEVEL___WORKAROUND_GUARD 0
+#endif
+#ifndef BOOST_GCC
+#define BOOST_GCC_WORKAROUND_GUARD 1
+#else
+#define BOOST_GCC_WORKAROUND_GUARD 0
+#endif
+#ifndef BOOST_XLCPP_ZOS
+#define BOOST_XLCPP_ZOS_WORKAROUND_GUARD 1
+#else
+#define BOOST_XLCPP_ZOS_WORKAROUND_GUARD 0
+#endif
+#ifndef __IBMCPP__
+#define __IBMCPP___WORKAROUND_GUARD 1
+#else
+#define __IBMCPP___WORKAROUND_GUARD 0
+#endif
+#ifndef __SUNPRO_CC
+#define __SUNPRO_CC_WORKAROUND_GUARD 1
+#else
+#define __SUNPRO_CC_WORKAROUND_GUARD 0
+#endif
+#ifndef __DECCXX_VER
+#define __DECCXX_VER_WORKAROUND_GUARD 1
+#else
+#define __DECCXX_VER_WORKAROUND_GUARD 0
+#endif
+#ifndef __MWERKS__
+#define __MWERKS___WORKAROUND_GUARD 1
+#else
+#define __MWERKS___WORKAROUND_GUARD 0
+#endif
+#ifndef __EDG__
+#define __EDG___WORKAROUND_GUARD 1
+#else
+#define __EDG___WORKAROUND_GUARD 0
+#endif
+#ifndef __EDG_VERSION__
+#define __EDG_VERSION___WORKAROUND_GUARD 1
+#else
+#define __EDG_VERSION___WORKAROUND_GUARD 0
+#endif
+#ifndef __HP_aCC
+#define __HP_aCC_WORKAROUND_GUARD 1
+#else
+#define __HP_aCC_WORKAROUND_GUARD 0
+#endif
+#ifndef __hpxstd98
+#define __hpxstd98_WORKAROUND_GUARD 1
+#else
+#define __hpxstd98_WORKAROUND_GUARD 0
+#endif
+#ifndef _CRAYC
+#define _CRAYC_WORKAROUND_GUARD 1
+#else
+#define _CRAYC_WORKAROUND_GUARD 0
+#endif
+#ifndef __DMC__
+#define __DMC___WORKAROUND_GUARD 1
+#else
+#define __DMC___WORKAROUND_GUARD 0
+#endif
+#ifndef MPW_CPLUS
+#define MPW_CPLUS_WORKAROUND_GUARD 1
+#else
+#define MPW_CPLUS_WORKAROUND_GUARD 0
+#endif
+#ifndef __COMO__
+#define __COMO___WORKAROUND_GUARD 1
+#else
+#define __COMO___WORKAROUND_GUARD 0
+#endif
+#ifndef __COMO_VERSION__
+#define __COMO_VERSION___WORKAROUND_GUARD 1
+#else
+#define __COMO_VERSION___WORKAROUND_GUARD 0
+#endif
+#ifndef __INTEL_COMPILER
+#define __INTEL_COMPILER_WORKAROUND_GUARD 1
+#else
+#define __INTEL_COMPILER_WORKAROUND_GUARD 0
+#endif
+#ifndef __ICL
+#define __ICL_WORKAROUND_GUARD 1
+#else
+#define __ICL_WORKAROUND_GUARD 0
+#endif
+#ifndef _COMPILER_VERSION
+#define _COMPILER_VERSION_WORKAROUND_GUARD 1
+#else
+#define _COMPILER_VERSION_WORKAROUND_GUARD 0
+#endif
+
+#ifndef _RWSTD_VER
+#define _RWSTD_VER_WORKAROUND_GUARD 1
+#else
+#define _RWSTD_VER_WORKAROUND_GUARD 0
+#endif
+#ifndef BOOST_RWSTD_VER
+#define BOOST_RWSTD_VER_WORKAROUND_GUARD 1
+#else
+#define BOOST_RWSTD_VER_WORKAROUND_GUARD 0
+#endif
+#ifndef __GLIBCPP__
+#define __GLIBCPP___WORKAROUND_GUARD 1
+#else
+#define __GLIBCPP___WORKAROUND_GUARD 0
+#endif
+#ifndef _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC
+#define _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC_WORKAROUND_GUARD 1
+#else
+#define _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC_WORKAROUND_GUARD 0
+#endif
+#ifndef __SGI_STL_PORT
+#define __SGI_STL_PORT_WORKAROUND_GUARD 1
+#else
+#define __SGI_STL_PORT_WORKAROUND_GUARD 0
+#endif
+#ifndef _STLPORT_VERSION
+#define _STLPORT_VERSION_WORKAROUND_GUARD 1
+#else
+#define _STLPORT_VERSION_WORKAROUND_GUARD 0
+#endif
+#ifndef __LIBCOMO_VERSION__
+#define __LIBCOMO_VERSION___WORKAROUND_GUARD 1
+#else
+#define __LIBCOMO_VERSION___WORKAROUND_GUARD 0
+#endif
+#ifndef _CPPLIB_VER
+#define _CPPLIB_VER_WORKAROUND_GUARD 1
+#else
+#define _CPPLIB_VER_WORKAROUND_GUARD 0
+#endif
+
+#ifndef BOOST_INTEL_CXX_VERSION
+#define BOOST_INTEL_CXX_VERSION_WORKAROUND_GUARD 1
+#else
+#define BOOST_INTEL_CXX_VERSION_WORKAROUND_GUARD 0
+#endif
+#ifndef BOOST_INTEL_WIN
+#define BOOST_INTEL_WIN_WORKAROUND_GUARD 1
+#else
+#define BOOST_INTEL_WIN_WORKAROUND_GUARD 0
+#endif
+#ifndef BOOST_DINKUMWARE_STDLIB
+#define BOOST_DINKUMWARE_STDLIB_WORKAROUND_GUARD 1
+#else
+#define BOOST_DINKUMWARE_STDLIB_WORKAROUND_GUARD 0
+#endif
+#ifndef BOOST_INTEL
+#define BOOST_INTEL_WORKAROUND_GUARD 1
+#else
+#define BOOST_INTEL_WORKAROUND_GUARD 0
+#endif
+// Always define to zero, if it's used it'll be defined my MPL:
+#define BOOST_MPL_CFG_GCC_WORKAROUND_GUARD 0
+
+#define BOOST_WORKAROUND(symbol, test) \
+ ((symbol ## _WORKAROUND_GUARD + 0 == 0) && \
+ (symbol != 0) && (1 % (( (symbol test) ) + 1)))
+// ^ ^ ^ ^
+// The extra level of parenthesis nesting above, along with the
+// BOOST_OPEN_PAREN indirection below, is required to satisfy the
+// broken preprocessor in MWCW 8.3 and earlier.
+//
+// The basic mechanism works as follows:
+// (symbol test) + 1 => if (symbol test) then 2 else 1
+// 1 % ((symbol test) + 1) => if (symbol test) then 1 else 0
+//
+// The complication with % is for cooperation with BOOST_TESTED_AT().
+// When "test" is BOOST_TESTED_AT(x) and
+// BOOST_DETECT_OUTDATED_WORKAROUNDS is #defined,
+//
+// symbol test => if (symbol <= x) then 1 else -1
+// (symbol test) + 1 => if (symbol <= x) then 2 else 0
+// 1 % ((symbol test) + 1) => if (symbol <= x) then 1 else divide-by-zero
+//
+
+#ifdef BOOST_DETECT_OUTDATED_WORKAROUNDS
+# define BOOST_OPEN_PAREN (
+# define BOOST_TESTED_AT(value) > value) ?(-1): BOOST_OPEN_PAREN 1
+#else
+# define BOOST_TESTED_AT(value) != ((value)-(value))
+#endif
+
+#else
+
+#define BOOST_WORKAROUND(symbol, test) 0
+
+#endif
+
+#endif // BOOST_CONFIG_WORKAROUND_HPP
diff --git a/boost/container/allocator_traits.hpp b/boost/container/allocator_traits.hpp
index d6621f614a..b08f601461 100644
--- a/boost/container/allocator_traits.hpp
+++ b/boost/container/allocator_traits.hpp
@@ -347,7 +347,7 @@ struct allocator_traits
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: calls <code>a.construct(p, std::forward<Args>(args)...)</code> if that call is well-formed;
- //! otherwise, invokes <code>::new (static_cast<void*>(p)) T(std::forward<Args>(args)...)</code>
+ //! otherwise, invokes <code>`placement new` (static_cast<void*>(p)) T(std::forward<Args>(args)...)</code>
template <class T, class ...Args>
BOOST_CONTAINER_FORCEINLINE static void construct(Allocator & a, T* p, BOOST_FWD_REF(Args)... args)
{
diff --git a/boost/container/deque.hpp b/boost/container/deque.hpp
index 255cd9399d..b838f6e4eb 100644
--- a/boost/container/deque.hpp
+++ b/boost/container/deque.hpp
@@ -31,11 +31,11 @@
#include <boost/container/detail/alloc_helpers.hpp>
#include <boost/container/detail/copy_move_algo.hpp>
#include <boost/container/detail/iterator.hpp>
-#include <boost/container/detail/iterator_to_raw_pointer.hpp>
+#include <boost/move/detail/iterator_to_raw_pointer.hpp>
#include <boost/container/detail/iterators.hpp>
#include <boost/container/detail/min_max.hpp>
#include <boost/container/detail/mpl.hpp>
-#include <boost/container/detail/to_raw_pointer.hpp>
+#include <boost/move/detail/to_raw_pointer.hpp>
#include <boost/container/detail/type_traits.hpp>
// move
#include <boost/move/adl_move_swap.hpp>
@@ -1649,7 +1649,7 @@ class deque : protected deque_base<Allocator>
if (this->members_.m_start.m_cur != this->members_.m_start.m_last - 1) {
allocator_traits_type::destroy
( this->alloc()
- , container_detail::to_raw_pointer(this->members_.m_start.m_cur)
+ , boost::movelib::to_raw_pointer(this->members_.m_start.m_cur)
);
++this->members_.m_start.m_cur;
}
@@ -1669,7 +1669,7 @@ class deque : protected deque_base<Allocator>
--this->members_.m_finish.m_cur;
allocator_traits_type::destroy
( this->alloc()
- , container_detail::to_raw_pointer(this->members_.m_finish.m_cur)
+ , boost::movelib::to_raw_pointer(this->members_.m_finish.m_cur)
);
}
else
@@ -1916,7 +1916,7 @@ class deque : protected deque_base<Allocator>
T *priv_push_back_simple_pos() const
{
- return container_detail::to_raw_pointer(this->members_.m_finish.m_cur);
+ return boost::movelib::to_raw_pointer(this->members_.m_finish.m_cur);
}
void priv_push_back_simple_commit()
@@ -1931,7 +1931,7 @@ class deque : protected deque_base<Allocator>
}
T *priv_push_front_simple_pos() const
- { return container_detail::to_raw_pointer(this->members_.m_start.m_cur) - 1; }
+ { return boost::movelib::to_raw_pointer(this->members_.m_start.m_cur) - 1; }
void priv_push_front_simple_commit()
{ --this->members_.m_start.m_cur; }
@@ -1940,7 +1940,7 @@ class deque : protected deque_base<Allocator>
{
if(!Base::traits_t::trivial_dctr){
for(;p != p2; ++p){
- allocator_traits_type::destroy(this->alloc(), container_detail::iterator_to_raw_pointer(p));
+ allocator_traits_type::destroy(this->alloc(), boost::movelib::iterator_to_raw_pointer(p));
}
}
}
@@ -1949,7 +1949,7 @@ class deque : protected deque_base<Allocator>
{
if(!Base::traits_t::trivial_dctr){
for(;p != p2; ++p){
- allocator_traits_type::destroy(this->alloc(), container_detail::iterator_to_raw_pointer(p));
+ allocator_traits_type::destroy(this->alloc(), boost::movelib::iterator_to_raw_pointer(p));
}
}
}
@@ -2133,7 +2133,7 @@ class deque : protected deque_base<Allocator>
this->members_.m_finish.m_cur = this->members_.m_finish.m_last - 1;
allocator_traits_type::destroy
( this->alloc()
- , container_detail::to_raw_pointer(this->members_.m_finish.m_cur)
+ , boost::movelib::to_raw_pointer(this->members_.m_finish.m_cur)
);
}
@@ -2145,7 +2145,7 @@ class deque : protected deque_base<Allocator>
{
allocator_traits_type::destroy
( this->alloc()
- , container_detail::to_raw_pointer(this->members_.m_start.m_cur)
+ , boost::movelib::to_raw_pointer(this->members_.m_start.m_cur)
);
this->priv_deallocate_node(this->members_.m_start.m_first);
this->members_.m_start.priv_set_node(this->members_.m_start.m_node + 1);
diff --git a/boost/container/detail/adaptive_node_pool_impl.hpp b/boost/container/detail/adaptive_node_pool_impl.hpp
index 24c81dda3b..54db19dff2 100644
--- a/boost/container/detail/adaptive_node_pool_impl.hpp
+++ b/boost/container/detail/adaptive_node_pool_impl.hpp
@@ -28,10 +28,10 @@
// container/detail
#include <boost/container/detail/pool_common.hpp>
#include <boost/container/detail/iterator.hpp>
-#include <boost/container/detail/iterator_to_raw_pointer.hpp>
+#include <boost/move/detail/iterator_to_raw_pointer.hpp>
#include <boost/container/detail/math_functions.hpp>
#include <boost/container/detail/mpl.hpp>
-#include <boost/container/detail/to_raw_pointer.hpp>
+#include <boost/move/detail/to_raw_pointer.hpp>
#include <boost/container/detail/type_traits.hpp>
// intrusive
#include <boost/intrusive/pointer_traits.hpp>
@@ -378,7 +378,7 @@ class private_adaptive_node_pool_impl
//!Returns the segment manager. Never throws
segment_manager_base_type* get_segment_manager_base()const
- { return container_detail::to_raw_pointer(mp_segment_mngr_base); }
+ { return boost::movelib::to_raw_pointer(mp_segment_mngr_base); }
//!Allocates array of count elements. Can throw
void *allocate_node()
@@ -390,7 +390,7 @@ class private_adaptive_node_pool_impl
free_nodes_t &free_nodes = m_block_container.begin()->free_nodes;
BOOST_ASSERT(!free_nodes.empty());
const size_type free_nodes_count = free_nodes.size();
- void *first_node = container_detail::to_raw_pointer(free_nodes.pop_front());
+ void *first_node = boost::movelib::to_raw_pointer(free_nodes.pop_front());
if(free_nodes.empty()){
block_container_traits_t::erase_first(m_block_container);
}
@@ -401,7 +401,7 @@ class private_adaptive_node_pool_impl
else{
multiallocation_chain chain;
this->priv_append_from_new_blocks(1, chain, IsAlignOnly());
- return container_detail::to_raw_pointer(chain.pop_front());
+ return boost::movelib::to_raw_pointer(chain.pop_front());
}
}
@@ -492,7 +492,7 @@ class private_adaptive_node_pool_impl
free_nodes_iterator itf(nodes.begin()), itbf(itbb);
size_type splice_node_count = size_type(-1);
while(itf != ite){
- void *pElem = container_detail::to_raw_pointer(container_detail::iterator_to_raw_pointer(itf));
+ void *pElem = boost::movelib::to_raw_pointer(boost::movelib::iterator_to_raw_pointer(itf));
block_info_t &block_info = *this->priv_block_from_node(pElem);
BOOST_ASSERT(block_info.free_nodes.size() < m_real_num_node);
++splice_node_count;
@@ -631,7 +631,7 @@ class private_adaptive_node_pool_impl
BOOST_ASSERT(to_deallocate->free_nodes.size() == mp_impl->m_real_num_node);
BOOST_ASSERT(0 == to_deallocate->hdr_offset);
hdr_offset_holder *hdr_off_holder =
- mp_impl->priv_first_subblock_from_block(container_detail::to_raw_pointer(to_deallocate));
+ mp_impl->priv_first_subblock_from_block(boost::movelib::to_raw_pointer(to_deallocate));
m_chain.push_back(hdr_off_holder);
}
@@ -763,7 +763,7 @@ class private_adaptive_node_pool_impl
//First add all possible nodes to the chain
const size_type left = total_elements - chain.size();
const size_type max_chain = (num_node < left) ? num_node : left;
- mem_address = static_cast<char *>(container_detail::to_raw_pointer
+ mem_address = static_cast<char *>(boost::movelib::to_raw_pointer
(chain.incorporate_after(chain.last(), void_pointer(mem_address), m_real_node_size, max_chain)));
//Now store remaining nodes in the free list
if(const size_type max_free = num_node - max_chain){
diff --git a/boost/container/detail/advanced_insert_int.hpp b/boost/container/detail/advanced_insert_int.hpp
index 1050857c46..20adb523a6 100644
--- a/boost/container/detail/advanced_insert_int.hpp
+++ b/boost/container/detail/advanced_insert_int.hpp
@@ -31,7 +31,7 @@
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/iterator.hpp>
#include <boost/container/detail/iterators.hpp>
-#include <boost/container/detail/iterator_to_raw_pointer.hpp>
+#include <boost/move/detail/iterator_to_raw_pointer.hpp>
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#include <boost/move/detail/fwd_macros.hpp>
#endif
@@ -157,7 +157,7 @@ struct insert_copy_proxy
void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
- alloc_traits::construct( a, iterator_to_raw_pointer(p), v_);
+ alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), v_);
}
void copy_n_and_update(Allocator &, Iterator p, size_type n) const
@@ -184,7 +184,7 @@ struct insert_move_proxy
void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
- alloc_traits::construct( a, iterator_to_raw_pointer(p), ::boost::move(v_) );
+ alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::move(v_) );
}
void copy_n_and_update(Allocator &, Iterator p, size_type n) const
@@ -240,7 +240,7 @@ struct insert_nonmovable_emplace_proxy
void priv_uninitialized_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
{
BOOST_ASSERT(n == 1); (void)n;
- alloc_traits::construct( a, iterator_to_raw_pointer(p), ::boost::forward<Args>(get<IdxPack>(this->args_))... );
+ alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::forward<Args>(get<IdxPack>(this->args_))... );
}
protected:
@@ -354,7 +354,7 @@ struct insert_nonmovable_emplace_proxy##N\
void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)\
{\
BOOST_ASSERT(n == 1); (void)n;\
- alloc_traits::construct(a, iterator_to_raw_pointer(p) BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\
+ alloc_traits::construct(a, boost::movelib::iterator_to_raw_pointer(p) BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\
}\
\
void copy_n_and_update(Allocator &, Iterator, size_type)\
diff --git a/boost/container/detail/algorithm.hpp b/boost/container/detail/algorithm.hpp
index 67e7876345..11844220e1 100644
--- a/boost/container/detail/algorithm.hpp
+++ b/boost/container/detail/algorithm.hpp
@@ -29,6 +29,128 @@ namespace container {
using boost::intrusive::algo_equal;
using boost::intrusive::algo_lexicographical_compare;
+template<class Func>
+class binder1st
+{
+ public:
+ typedef typename Func::second_argument_type argument_type;
+ typedef typename Func::result_type result_type;
+
+ binder1st(const Func& func, const typename Func::first_argument_type& arg)
+ : op(func), value(arg)
+ {}
+
+ result_type operator()(const argument_type& arg) const
+ { return op(value, arg); }
+
+ result_type operator()(argument_type& arg) const
+ { return op(value, arg); }
+
+ private:
+ Func op;
+ typename Func::first_argument_type value;
+};
+
+template<class Func, class T>
+inline binder1st<Func> bind1st(const Func& func, const T& arg)
+{ return boost::container::binder1st<Func>(func, arg); }
+
+template<class Func>
+class binder2nd
+{
+ public:
+ typedef typename Func::first_argument_type argument_type;
+ typedef typename Func::result_type result_type;
+
+ binder2nd(const Func& func, const typename Func::second_argument_type& arg)
+ : op(func), value(arg)
+ {}
+
+ result_type operator()(const argument_type& arg) const
+ { return op(arg, value); }
+
+ result_type operator()(argument_type& arg) const
+ { return op(arg, value); }
+
+ private:
+ Func op;
+ typename Func::second_argument_type value;
+};
+
+template<class Func, class T>
+inline binder2nd<Func> bind2nd(const Func& func, const T& arg)
+{
+ return (boost::container::binder2nd<Func>(func, arg));
+}
+
+template<class Func>
+class unary_negate
+{
+ public:
+ typedef typename Func::argument_type argument_type;
+ typedef typename Func::result_type result_type;
+
+ explicit unary_negate(const Func& func)
+ : m_func(func)
+ {}
+
+ bool operator()(const typename Func::argument_type& arg) const
+ { return !m_func(arg); }
+
+ private:
+ Func m_func;
+};
+
+template<class Func> inline
+unary_negate<Func> not1(const Func& func)
+{
+ return boost::container::unary_negate<Func>(func);
+}
+
+template<class InputIt, class UnaryPredicate>
+InputIt find_if(InputIt first, InputIt last, UnaryPredicate p)
+{
+ for (; first != last; ++first) {
+ if (p(*first)) {
+ return first;
+ }
+ }
+ return last;
+}
+
+template<class InputIt, class ForwardIt, class BinaryPredicate>
+InputIt find_first_of(InputIt first1, InputIt last1, ForwardIt first2, ForwardIt last2, BinaryPredicate p)
+{
+ for (; first1 != last1; ++first1) {
+ for (ForwardIt it = first2; it != last2; ++it) {
+ if (p(*first1, *it)) {
+ return first1;
+ }
+ }
+ }
+ return last1;
+}
+
+template<class ForwardIt1, class ForwardIt2, class BinaryPredicate>
+ForwardIt1 search(ForwardIt1 first1, ForwardIt1 last1,
+ ForwardIt2 first2, ForwardIt2 last2, BinaryPredicate p)
+{
+ for (; ; ++first1) {
+ ForwardIt1 it = first1;
+ for (ForwardIt2 it2 = first2; ; ++it, ++it2) {
+ if (it2 == last2) {
+ return first1;
+ }
+ if (it == last1) {
+ return last1;
+ }
+ if (!p(*it, *it2)) {
+ break;
+ }
+ }
+ }
+}
+
} //namespace container {
} //namespace boost {
diff --git a/boost/container/detail/copy_move_algo.hpp b/boost/container/detail/copy_move_algo.hpp
index dda311aa33..9044960e79 100644
--- a/boost/container/detail/copy_move_algo.hpp
+++ b/boost/container/detail/copy_move_algo.hpp
@@ -22,7 +22,7 @@
#include <boost/container/allocator_traits.hpp>
// container/detail
#include <boost/container/detail/iterator.hpp>
-#include <boost/container/detail/iterator_to_raw_pointer.hpp>
+#include <boost/move/detail/iterator_to_raw_pointer.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/construct_in_place.hpp>
@@ -178,7 +178,7 @@ inline F memmove(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
typedef typename boost::container::iterator_traits<I>::value_type value_type;
typename boost::container::iterator_traits<I>::difference_type n = boost::container::iterator_distance(f, l);
if(n){
- std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
+ std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
boost::container::iterator_advance(r, n);
}
return r;
@@ -192,7 +192,7 @@ F memmove_n(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
{
typedef typename boost::container::iterator_traits<I>::value_type value_type;
if(n){
- std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
+ std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
boost::container::iterator_advance(r, n);
}
return r;
@@ -206,7 +206,7 @@ I memmove_n_source(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
{
if(n){
typedef typename boost::container::iterator_traits<I>::value_type value_type;
- std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
+ std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
boost::container::iterator_advance(f, n);
}
return f;
@@ -220,7 +220,7 @@ I memmove_n_source_dest(I f, U n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
{
typedef typename boost::container::iterator_traits<I>::value_type value_type;
if(n){
- std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
+ std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
boost::container::iterator_advance(f, n);
boost::container::iterator_advance(r, n);
}
@@ -295,13 +295,13 @@ inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F
F back = r;
BOOST_TRY{
while (f != l) {
- allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f));
+ allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), boost::move(*f));
++f; ++r;
}
}
BOOST_CATCH(...){
for (; back != r; ++back){
- allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
}
BOOST_RETHROW;
}
@@ -340,13 +340,13 @@ inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F
F back = r;
BOOST_TRY{
while (n--) {
- allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f));
+ allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), boost::move(*f));
++f; ++r;
}
}
BOOST_CATCH(...){
for (; back != r; ++back){
- allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
}
BOOST_RETHROW;
}
@@ -385,13 +385,13 @@ inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F
F back = r;
BOOST_TRY{
while (n--) {
- allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f));
+ allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), boost::move(*f));
++f; ++r;
}
}
BOOST_CATCH(...){
for (; back != r; ++back){
- allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
}
BOOST_RETHROW;
}
@@ -430,13 +430,13 @@ inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F
F back = r;
BOOST_TRY{
while (f != l) {
- allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), *f);
+ allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), *f);
++f; ++r;
}
}
BOOST_CATCH(...){
for (; back != r; ++back){
- allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
}
BOOST_RETHROW;
}
@@ -475,13 +475,13 @@ inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F
F back = r;
BOOST_TRY{
while (n--) {
- allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), *f);
+ allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), *f);
++f; ++r;
}
}
BOOST_CATCH(...){
for (; back != r; ++back){
- allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
}
BOOST_RETHROW;
}
@@ -520,13 +520,13 @@ inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F
F back = r;
BOOST_TRY{
while (n--) {
- boost::container::construct_in_place(a, container_detail::iterator_to_raw_pointer(r), f);
+ boost::container::construct_in_place(a, boost::movelib::iterator_to_raw_pointer(r), f);
++f; ++r;
}
}
BOOST_CATCH(...){
for (; back != r; ++back){
- allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
}
BOOST_RETHROW;
}
@@ -564,13 +564,13 @@ inline typename container_detail::disable_if_memzero_initializable<F, F>::type
F back = r;
BOOST_TRY{
while (n--) {
- allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r));
+ allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r));
++r;
}
}
BOOST_CATCH(...){
for (; back != r; ++back){
- allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
}
BOOST_RETHROW;
}
@@ -585,7 +585,7 @@ inline typename container_detail::enable_if_memzero_initializable<F, F>::type
uninitialized_value_init_alloc_n(Allocator &, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
{
typedef typename boost::container::iterator_traits<F>::value_type value_type;
- std::memset((void*)container_detail::iterator_to_raw_pointer(r), 0, sizeof(value_type)*n);
+ std::memset((void*)boost::movelib::iterator_to_raw_pointer(r), 0, sizeof(value_type)*n);
boost::container::iterator_advance(r, n);
return r;
}
@@ -611,13 +611,13 @@ inline F uninitialized_default_init_alloc_n(Allocator &a, typename boost::contai
F back = r;
BOOST_TRY{
while (n--) {
- allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), default_init);
+ allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), default_init);
++r;
}
}
BOOST_CATCH(...){
for (; back != r; ++back){
- allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
}
BOOST_RETHROW;
}
@@ -647,13 +647,13 @@ inline void uninitialized_fill_alloc(Allocator &a, F f, F l, const T &t)
F back = f;
BOOST_TRY{
while (f != l) {
- allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(f), t);
+ allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(f), t);
++f;
}
}
BOOST_CATCH(...){
for (; back != l; ++back){
- allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
}
BOOST_RETHROW;
}
@@ -683,13 +683,13 @@ inline F uninitialized_fill_alloc_n(Allocator &a, const T &v, typename boost::co
F back = r;
BOOST_TRY{
while (n--) {
- allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), v);
+ allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), v);
++r;
}
}
BOOST_CATCH(...){
for (; back != r; ++back){
- allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
}
BOOST_RETHROW;
}
@@ -890,7 +890,7 @@ inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F>
typedef typename boost::container::iterator_traits<I>::value_type value_type;
const typename boost::container::iterator_traits<I>::difference_type n = boost::container::iterator_distance(f, l);
r -= n;
- std::memmove((container_detail::iterator_to_raw_pointer)(r), (container_detail::iterator_to_raw_pointer)(f), sizeof(value_type)*n);
+ std::memmove((boost::movelib::iterator_to_raw_pointer)(r), (boost::movelib::iterator_to_raw_pointer)(f), sizeof(value_type)*n);
return r;
}
@@ -963,8 +963,9 @@ template
inline typename container_detail::disable_if_trivially_destructible<I, void>::type
destroy_alloc_n(Allocator &a, I f, U n)
{
- while(n--){
- allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(f));
+ while(n){
+ --n;
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(f));
++f;
}
}
@@ -1021,9 +1022,9 @@ inline typename container_detail::enable_if_c
storage_type storage;
const std::size_t n_i_bytes = sizeof(value_type)*n_i;
- void *const large_ptr = static_cast<void*>(container_detail::iterator_to_raw_pointer(large_range_f));
- void *const short_ptr = static_cast<void*>(container_detail::iterator_to_raw_pointer(short_range_f));
- void *const stora_ptr = static_cast<void*>(container_detail::iterator_to_raw_pointer(storage));
+ void *const large_ptr = static_cast<void*>(boost::movelib::iterator_to_raw_pointer(large_range_f));
+ void *const short_ptr = static_cast<void*>(boost::movelib::iterator_to_raw_pointer(short_range_f));
+ void *const stora_ptr = static_cast<void*>(boost::movelib::iterator_to_raw_pointer(storage));
std::memcpy(stora_ptr, large_ptr, n_i_bytes);
std::memcpy(large_ptr, short_ptr, n_i_bytes);
std::memcpy(short_ptr, stora_ptr, n_i_bytes);
@@ -1052,8 +1053,8 @@ inline typename container_detail::enable_if_c
const std::size_t sizeof_storage = sizeof(storage);
std::size_t n_i_bytes = sizeof(value_type)*n_i;
- char *large_ptr = static_cast<char*>(static_cast<void*>(container_detail::iterator_to_raw_pointer(large_range_f)));
- char *short_ptr = static_cast<char*>(static_cast<void*>(container_detail::iterator_to_raw_pointer(short_range_f)));
+ char *large_ptr = static_cast<char*>(static_cast<void*>(boost::movelib::iterator_to_raw_pointer(large_range_f)));
+ char *short_ptr = static_cast<char*>(static_cast<void*>(boost::movelib::iterator_to_raw_pointer(short_range_f)));
char *stora_ptr = static_cast<char*>(static_cast<void*>(&storage));
std::size_t szt_times = n_i_bytes/sizeof_storage;
diff --git a/boost/container/detail/destroyers.hpp b/boost/container/detail/destroyers.hpp
index 52b44c0363..b110561a4a 100644
--- a/boost/container/detail/destroyers.hpp
+++ b/boost/container/detail/destroyers.hpp
@@ -25,7 +25,7 @@
#include <boost/container/detail/workaround.hpp>
#include <boost/container/allocator_traits.hpp>
-#include <boost/container/detail/to_raw_pointer.hpp>
+#include <boost/move/detail/to_raw_pointer.hpp>
#include <boost/container/detail/version_type.hpp>
namespace boost {
@@ -152,7 +152,7 @@ struct scoped_destroy_deallocator
~scoped_destroy_deallocator()
{
if(m_ptr){
- AllocTraits::destroy(m_alloc, container_detail::to_raw_pointer(m_ptr));
+ AllocTraits::destroy(m_alloc, boost::movelib::to_raw_pointer(m_ptr));
priv_deallocate(m_ptr, alloc_version());
}
}
@@ -202,7 +202,7 @@ struct scoped_destructor_n
~scoped_destructor_n()
{
if(!m_p) return;
- value_type *raw_ptr = container_detail::to_raw_pointer(m_p);
+ value_type *raw_ptr = boost::movelib::to_raw_pointer(m_p);
while(m_n--){
AllocTraits::destroy(m_a, raw_ptr++);
}
@@ -317,7 +317,7 @@ class allocator_destroyer
void operator()(const pointer &p)
{
- AllocTraits::destroy(a_, container_detail::to_raw_pointer(p));
+ AllocTraits::destroy(a_, boost::movelib::to_raw_pointer(p));
this->priv_deallocate(p, alloc_version());
}
};
@@ -339,7 +339,7 @@ class allocator_destroyer_and_chain_builder
void operator()(const typename Allocator::pointer &p)
{
- allocator_traits<Allocator>::destroy(a_, container_detail::to_raw_pointer(p));
+ allocator_traits<Allocator>::destroy(a_, boost::movelib::to_raw_pointer(p));
c_.push_back(p);
}
};
diff --git a/boost/container/detail/flat_tree.hpp b/boost/container/detail/flat_tree.hpp
index 93984d18e5..9aab87308a 100644
--- a/boost/container/detail/flat_tree.hpp
+++ b/boost/container/detail/flat_tree.hpp
@@ -28,25 +28,30 @@
#include <boost/container/detail/pair.hpp>
#include <boost/container/vector.hpp>
+#include <boost/container/allocator_traits.hpp>
+
#include <boost/container/detail/value_init.hpp>
#include <boost/container/detail/destroyers.hpp>
#include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare
#include <boost/container/detail/iterator.hpp>
#include <boost/container/detail/is_sorted.hpp>
-#include <boost/container/allocator_traits.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/detail/iterators.hpp>
+
#ifdef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
#include <boost/intrusive/pointer_traits.hpp>
#endif
-#include <boost/container/detail/type_traits.hpp>
-#include <boost/container/detail/iterators.hpp>
+#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
+
#include <boost/move/make_unique.hpp>
+#include <boost/move/iterator.hpp>
#include <boost/move/adl_move_swap.hpp>
+#include <boost/move/algo/adaptive_sort.hpp>
+
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#include <boost/move/detail/fwd_macros.hpp>
#endif
-#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
-#include <boost/move/iterator.hpp>
namespace boost {
namespace container {
@@ -105,14 +110,17 @@ template <class Value, class KeyOfValue,
class Compare, class Allocator>
class flat_tree
{
- typedef boost::container::vector<Value, Allocator> vector_t;
+ public:
+ typedef boost::container::vector<Value, Allocator> sequence_type;
+
+ private:
typedef Allocator allocator_t;
typedef allocator_traits<Allocator> allocator_traits_type;
public:
typedef flat_tree_value_compare<Compare, Value, KeyOfValue> value_compare;
- private:
+ private:
struct Data
//Inherit from value_compare to do EBO
: public value_compare
@@ -121,48 +129,48 @@ class flat_tree
public:
Data()
- : value_compare(), m_vect()
+ : value_compare(), m_seq()
{}
- explicit Data(const Data &d)
- : value_compare(static_cast<const value_compare&>(d)), m_vect(d.m_vect)
+ explicit Data(const allocator_t &alloc)
+ : value_compare(), m_seq(alloc)
{}
- Data(BOOST_RV_REF(Data) d)
- : value_compare(boost::move(static_cast<value_compare&>(d))), m_vect(boost::move(d.m_vect))
+ explicit Data(const Compare &comp)
+ : value_compare(comp), m_seq()
{}
- Data(const Data &d, const Allocator &a)
- : value_compare(static_cast<const value_compare&>(d)), m_vect(d.m_vect, a)
+ Data(const Compare &comp, const allocator_t &alloc)
+ : value_compare(comp), m_seq(alloc)
{}
- Data(BOOST_RV_REF(Data) d, const Allocator &a)
- : value_compare(boost::move(static_cast<value_compare&>(d))), m_vect(boost::move(d.m_vect), a)
+ explicit Data(const Data &d)
+ : value_compare(static_cast<const value_compare&>(d)), m_seq(d.m_seq)
{}
- explicit Data(const Compare &comp)
- : value_compare(comp), m_vect()
+ Data(BOOST_RV_REF(Data) d)
+ : value_compare(boost::move(static_cast<value_compare&>(d))), m_seq(boost::move(d.m_seq))
{}
- Data(const Compare &comp, const allocator_t &alloc)
- : value_compare(comp), m_vect(alloc)
+ Data(const Data &d, const Allocator &a)
+ : value_compare(static_cast<const value_compare&>(d)), m_seq(d.m_seq, a)
{}
- explicit Data(const allocator_t &alloc)
- : value_compare(), m_vect(alloc)
+ Data(BOOST_RV_REF(Data) d, const Allocator &a)
+ : value_compare(boost::move(static_cast<value_compare&>(d))), m_seq(boost::move(d.m_seq), a)
{}
Data& operator=(BOOST_COPY_ASSIGN_REF(Data) d)
{
this->value_compare::operator=(d);
- m_vect = d.m_vect;
+ m_seq = d.m_seq;
return *this;
}
Data& operator=(BOOST_RV_REF(Data) d)
{
this->value_compare::operator=(boost::move(static_cast<value_compare &>(d)));
- m_vect = boost::move(d.m_vect);
+ m_seq = boost::move(d.m_seq);
return *this;
}
@@ -170,10 +178,10 @@ class flat_tree
{
value_compare& mycomp = *this, & othercomp = d;
boost::adl_move_swap(mycomp, othercomp);
- this->m_vect.swap(d.m_vect);
+ this->m_seq.swap(d.m_seq);
}
- vector_t m_vect;
+ sequence_type m_seq;
};
Data m_data;
@@ -181,23 +189,23 @@ class flat_tree
public:
- typedef typename vector_t::value_type value_type;
- typedef typename vector_t::pointer pointer;
- typedef typename vector_t::const_pointer const_pointer;
- typedef typename vector_t::reference reference;
- typedef typename vector_t::const_reference const_reference;
- typedef typename KeyOfValue::type key_type;
- typedef Compare key_compare;
- typedef typename vector_t::allocator_type allocator_type;
- typedef typename vector_t::size_type size_type;
- typedef typename vector_t::difference_type difference_type;
- typedef typename vector_t::iterator iterator;
- typedef typename vector_t::const_iterator const_iterator;
- typedef typename vector_t::reverse_iterator reverse_iterator;
- typedef typename vector_t::const_reverse_iterator const_reverse_iterator;
+ typedef typename sequence_type::value_type value_type;
+ typedef typename sequence_type::pointer pointer;
+ typedef typename sequence_type::const_pointer const_pointer;
+ typedef typename sequence_type::reference reference;
+ typedef typename sequence_type::const_reference const_reference;
+ typedef typename KeyOfValue::type key_type;
+ typedef Compare key_compare;
+ typedef typename sequence_type::allocator_type allocator_type;
+ typedef typename sequence_type::size_type size_type;
+ typedef typename sequence_type::difference_type difference_type;
+ typedef typename sequence_type::iterator iterator;
+ typedef typename sequence_type::const_iterator const_iterator;
+ typedef typename sequence_type::reverse_iterator reverse_iterator;
+ typedef typename sequence_type::const_reverse_iterator const_reverse_iterator;
//!Standard extension
- typedef allocator_type stored_allocator_type;
+ typedef allocator_type stored_allocator_type;
private:
typedef allocator_traits<stored_allocator_type> stored_allocator_traits;
@@ -211,14 +219,14 @@ class flat_tree
: m_data(comp)
{ }
- BOOST_CONTAINER_FORCEINLINE flat_tree(const Compare& comp, const allocator_type& a)
- : m_data(comp, a)
- { }
-
BOOST_CONTAINER_FORCEINLINE explicit flat_tree(const allocator_type& a)
: m_data(a)
{ }
+ BOOST_CONTAINER_FORCEINLINE flat_tree(const Compare& comp, const allocator_type& a)
+ : m_data(comp, a)
+ { }
+
BOOST_CONTAINER_FORCEINLINE flat_tree(const flat_tree& x)
: m_data(x.m_data)
{ }
@@ -237,46 +245,92 @@ class flat_tree
{ }
template <class InputIterator>
- flat_tree( ordered_range_t, InputIterator first, InputIterator last
- , const Compare& comp = Compare()
- , const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( ordered_range_t, InputIterator first, InputIterator last)
+ : m_data()
+ {
+ this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
+ BOOST_ASSERT((is_sorted)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( ordered_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : m_data(comp)
+ {
+ this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
+ BOOST_ASSERT((is_sorted)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( ordered_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
: m_data(comp, a)
{
- this->m_data.m_vect.insert(this->m_data.m_vect.end(), first, last);
- BOOST_ASSERT((is_sorted)(this->m_data.m_vect.cbegin(), this->m_data.m_vect.cend(), this->priv_value_comp()));
+ this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
+ BOOST_ASSERT((is_sorted)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last)
+ : m_data()
+ {
+ this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
+ BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
}
template <class InputIterator>
- flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last
- , const Compare& comp = Compare()
- , const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : m_data(comp)
+ {
+ this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
+ BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
: m_data(comp, a)
{
- this->m_data.m_vect.insert(this->m_data.m_vect.end(), first, last);
- BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_vect.cbegin(), this->m_data.m_vect.cend(), this->priv_value_comp()));
+ this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
+ BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
}
template <class InputIterator>
- flat_tree( bool unique_insertion
- , InputIterator first, InputIterator last
- , const Compare& comp = Compare()
- , const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( bool unique_insertion, InputIterator first, InputIterator last)
+ : m_data()
+ {
+ this->priv_range_insertion_construct(unique_insertion, first, last);
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( bool unique_insertion, InputIterator first, InputIterator last
+ , const Compare& comp)
+ : m_data(comp)
+ {
+ this->priv_range_insertion_construct(unique_insertion, first, last);
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( bool unique_insertion, InputIterator first, InputIterator last
+ , const allocator_type& a)
+ : m_data(a)
+ {
+ this->priv_range_insertion_construct(unique_insertion, first, last);
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( bool unique_insertion, InputIterator first, InputIterator last
+ , const Compare& comp, const allocator_type& a)
: m_data(comp, a)
{
- //Use cend() as hint to achieve linear time for
- //ordered ranges as required by the standard
- //for the constructor
- //Call end() every iteration as reallocation might have invalidated iterators
- if(unique_insertion){
- for ( ; first != last; ++first){
- this->insert_unique(this->cend(), *first);
- }
- }
- else{
- for ( ; first != last; ++first){
- this->insert_equal(this->cend(), *first);
- }
- }
+ this->priv_range_insertion_construct(unique_insertion, first, last);
}
BOOST_CONTAINER_FORCEINLINE ~flat_tree()
@@ -312,31 +366,31 @@ class flat_tree
{ return this->m_data; }
BOOST_CONTAINER_FORCEINLINE allocator_type get_allocator() const
- { return this->m_data.m_vect.get_allocator(); }
+ { return this->m_data.m_seq.get_allocator(); }
BOOST_CONTAINER_FORCEINLINE const stored_allocator_type &get_stored_allocator() const
- { return this->m_data.m_vect.get_stored_allocator(); }
+ { return this->m_data.m_seq.get_stored_allocator(); }
BOOST_CONTAINER_FORCEINLINE stored_allocator_type &get_stored_allocator()
- { return this->m_data.m_vect.get_stored_allocator(); }
+ { return this->m_data.m_seq.get_stored_allocator(); }
BOOST_CONTAINER_FORCEINLINE iterator begin()
- { return this->m_data.m_vect.begin(); }
+ { return this->m_data.m_seq.begin(); }
BOOST_CONTAINER_FORCEINLINE const_iterator begin() const
{ return this->cbegin(); }
BOOST_CONTAINER_FORCEINLINE const_iterator cbegin() const
- { return this->m_data.m_vect.begin(); }
+ { return this->m_data.m_seq.begin(); }
BOOST_CONTAINER_FORCEINLINE iterator end()
- { return this->m_data.m_vect.end(); }
+ { return this->m_data.m_seq.end(); }
BOOST_CONTAINER_FORCEINLINE const_iterator end() const
{ return this->cend(); }
BOOST_CONTAINER_FORCEINLINE const_iterator cend() const
- { return this->m_data.m_vect.end(); }
+ { return this->m_data.m_seq.end(); }
BOOST_CONTAINER_FORCEINLINE reverse_iterator rbegin()
{ return reverse_iterator(this->end()); }
@@ -357,13 +411,13 @@ class flat_tree
{ return const_reverse_iterator(this->cbegin()); }
BOOST_CONTAINER_FORCEINLINE bool empty() const
- { return this->m_data.m_vect.empty(); }
+ { return this->m_data.m_seq.empty(); }
BOOST_CONTAINER_FORCEINLINE size_type size() const
- { return this->m_data.m_vect.size(); }
+ { return this->m_data.m_seq.size(); }
BOOST_CONTAINER_FORCEINLINE size_type max_size() const
- { return this->m_data.m_vect.max_size(); }
+ { return this->m_data.m_seq.max_size(); }
BOOST_CONTAINER_FORCEINLINE void swap(flat_tree& other)
BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
@@ -395,14 +449,14 @@ class flat_tree
iterator insert_equal(const value_type& val)
{
iterator i = this->upper_bound(KeyOfValue()(val));
- i = this->m_data.m_vect.insert(i, val);
+ i = this->m_data.m_seq.insert(i, val);
return i;
}
iterator insert_equal(BOOST_RV_REF(value_type) mval)
{
iterator i = this->upper_bound(KeyOfValue()(mval));
- i = this->m_data.m_vect.insert(i, boost::move(mval));
+ i = this->m_data.m_seq.insert(i, boost::move(mval));
return i;
}
@@ -509,7 +563,7 @@ class flat_tree
>::type * = 0
#endif
)
- { this->m_data.m_vect.merge(first, last, static_cast<const value_compare &>(this->m_data)); }
+ { this->m_data.m_seq.merge(first, last, static_cast<const value_compare &>(this->m_data)); }
template <class InIt>
void insert_unique(ordered_unique_range_t, InIt first, InIt last
@@ -538,7 +592,7 @@ class flat_tree
>::type * = 0
#endif
)
- { this->m_data.m_vect.merge_unique(first, last, static_cast<const value_compare &>(this->m_data)); }
+ { this->m_data.m_seq.merge_unique(first, last, static_cast<const value_compare &>(this->m_data)); }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
@@ -606,7 +660,7 @@ class flat_tree
typedef typename emplace_functor_type<try_emplace_t, KeyType, Args...>::type func_t;
typedef emplace_iterator<value_type, func_t, difference_type> it_t;
func_t func(try_emplace_t(), ::boost::forward<KeyType>(key), ::boost::forward<Args>(args)...);
- ret.first = this->m_data.m_vect.insert(data.position, it_t(func), it_t());
+ ret.first = this->m_data.m_seq.insert(data.position, it_t(func), it_t());
}
return ret;
}
@@ -675,7 +729,7 @@ class flat_tree
typedef typename emplace_functor_type<try_emplace_t, KeyType BOOST_MOVE_I##N BOOST_MOVE_TARG##N>::type func_t;\
typedef emplace_iterator<value_type, func_t, difference_type> it_t;\
func_t func(try_emplace_t(), ::boost::forward<KeyType>(key) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
- ret.first = this->m_data.m_vect.insert(data.position, it_t(func), it_t());\
+ ret.first = this->m_data.m_seq.insert(data.position, it_t(func), it_t());\
}\
return ret;\
}\
@@ -702,29 +756,29 @@ class flat_tree
typedef typename emplace_functor_type<KeyType, M>::type func_t;
typedef emplace_iterator<value_type, func_t, difference_type> it_t;
func_t func(boost::forward<KeyType>(key), boost::forward<M>(obj));
- ret.first = this->m_data.m_vect.insert(data.position, it_t(func), it_t());
+ ret.first = this->m_data.m_seq.insert(data.position, it_t(func), it_t());
}
return ret;
}
BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator position)
- { return this->m_data.m_vect.erase(position); }
+ { return this->m_data.m_seq.erase(position); }
size_type erase(const key_type& k)
{
std::pair<iterator,iterator > itp = this->equal_range(k);
size_type ret = static_cast<size_type>(itp.second-itp.first);
if (ret){
- this->m_data.m_vect.erase(itp.first, itp.second);
+ this->m_data.m_seq.erase(itp.first, itp.second);
}
return ret;
}
BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator first, const_iterator last)
- { return this->m_data.m_vect.erase(first, last); }
+ { return this->m_data.m_seq.erase(first, last); }
BOOST_CONTAINER_FORCEINLINE void clear()
- { this->m_data.m_vect.clear(); }
+ { this->m_data.m_seq.clear(); }
//! <b>Effects</b>: Tries to deallocate the excess of memory created
// with previous allocations. The size of the vector is unchanged
@@ -733,19 +787,19 @@ class flat_tree
//!
//! <b>Complexity</b>: Linear to size().
BOOST_CONTAINER_FORCEINLINE void shrink_to_fit()
- { this->m_data.m_vect.shrink_to_fit(); }
+ { this->m_data.m_seq.shrink_to_fit(); }
BOOST_CONTAINER_FORCEINLINE iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
- { return this->m_data.m_vect.nth(n); }
+ { return this->m_data.m_seq.nth(n); }
BOOST_CONTAINER_FORCEINLINE const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
- { return this->m_data.m_vect.nth(n); }
+ { return this->m_data.m_seq.nth(n); }
BOOST_CONTAINER_FORCEINLINE size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
- { return this->m_data.m_vect.index_of(p); }
+ { return this->m_data.m_seq.index_of(p); }
BOOST_CONTAINER_FORCEINLINE size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
- { return this->m_data.m_vect.index_of(p); }
+ { return this->m_data.m_seq.index_of(p); }
// set operations:
iterator find(const key_type& k)
@@ -793,7 +847,7 @@ class flat_tree
void merge_unique(flat_tree& source)
{
- this->m_data.m_vect.merge_unique
+ this->m_data.m_seq.merge_unique
( boost::make_move_iterator(source.begin())
, boost::make_move_iterator(source.end())
, static_cast<const value_compare &>(this->m_data));
@@ -801,7 +855,7 @@ class flat_tree
void merge_equal(flat_tree& source)
{
- this->m_data.m_vect.merge
+ this->m_data.m_seq.merge
( boost::make_move_iterator(source.begin())
, boost::make_move_iterator(source.end())
, static_cast<const value_compare &>(this->m_data));
@@ -832,10 +886,61 @@ class flat_tree
{ return this->priv_lower_bound_range(this->cbegin(), this->cend(), k); }
BOOST_CONTAINER_FORCEINLINE size_type capacity() const
- { return this->m_data.m_vect.capacity(); }
+ { return this->m_data.m_seq.capacity(); }
BOOST_CONTAINER_FORCEINLINE void reserve(size_type cnt)
- { this->m_data.m_vect.reserve(cnt); }
+ { this->m_data.m_seq.reserve(cnt); }
+
+ BOOST_CONTAINER_FORCEINLINE sequence_type extract_sequence()
+ {
+ return boost::move(m_data.m_seq);
+ }
+
+ BOOST_CONTAINER_FORCEINLINE sequence_type &get_sequence_ref()
+ {
+ return m_data.m_seq;
+ }
+
+ void adopt_sequence_equal(BOOST_RV_REF(sequence_type) seq)
+ {
+ sequence_type &tseq = m_data.m_seq;
+ boost::movelib::adaptive_sort
+ ( boost::movelib::iterator_to_raw_pointer(seq.begin())
+ , boost::movelib::iterator_to_raw_pointer(seq.end())
+ , this->priv_value_comp()
+ , boost::movelib::iterator_to_raw_pointer(tseq.begin() + tseq.size())
+ , tseq.capacity() - tseq.size());
+ tseq = boost::move(seq);
+ }
+
+ void adopt_sequence_equal(ordered_range_t, BOOST_RV_REF(sequence_type) seq)
+ {
+ BOOST_ASSERT((is_sorted)(seq.cbegin(), seq.cend(), this->priv_value_comp()));
+ sequence_type &tseq = m_data.m_seq;
+ tseq = boost::move(seq);
+ }
+
+ void adopt_sequence_unique(BOOST_RV_REF(sequence_type) seq)
+ {
+ sequence_type &tseq = m_data.m_seq;
+ boost::movelib::adaptive_sort
+ ( boost::movelib::iterator_to_raw_pointer(seq.begin())
+ , boost::movelib::iterator_to_raw_pointer(seq.end())
+ , this->priv_value_comp()
+ , boost::movelib::iterator_to_raw_pointer(tseq.begin() + tseq.size())
+ , tseq.capacity() - tseq.size());
+ seq.erase( boost::movelib::unique
+ (seq.begin(), seq.end(), boost::movelib::negate<value_compare>(this->m_data.get_comp()))
+ , seq.cend());
+ tseq = boost::move(seq);
+ }
+
+ void adopt_sequence_unique(ordered_unique_range_t, BOOST_RV_REF(sequence_type) seq)
+ {
+ BOOST_ASSERT((is_sorted_and_unique)(seq.cbegin(), seq.cend(), this->priv_value_comp()));
+ sequence_type &tseq = m_data.m_seq;
+ tseq = boost::move(seq);
+ }
BOOST_CONTAINER_FORCEINLINE friend bool operator==(const flat_tree& x, const flat_tree& y)
{
@@ -864,6 +969,25 @@ class flat_tree
private:
+ template <class InputIterator>
+ void priv_range_insertion_construct( bool unique_insertion, InputIterator first, InputIterator last)
+ {
+ //Use cend() as hint to achieve linear time for
+ //ordered ranges as required by the standard
+ //for the constructor
+ //Call end() every iteration as reallocation might have invalidated iterators
+ if(unique_insertion){
+ for ( ; first != last; ++first){
+ this->insert_unique(this->cend(), *first);
+ }
+ }
+ else{
+ for ( ; first != last; ++first){
+ this->insert_equal(this->cend(), *first);
+ }
+ }
+ }
+
BOOST_CONTAINER_FORCEINLINE bool priv_in_range_or_end(const_iterator pos) const
{
return (this->begin() <= pos) && (pos <= this->end());
@@ -963,7 +1087,7 @@ class flat_tree
BOOST_CONTAINER_FORCEINLINE iterator priv_insert_commit
(insert_commit_data &commit_data, BOOST_FWD_REF(Convertible) convertible)
{
- return this->m_data.m_vect.insert
+ return this->m_data.m_seq.insert
( commit_data.position
, boost::forward<Convertible>(convertible));
}
diff --git a/boost/container/detail/iterator_to_raw_pointer.hpp b/boost/container/detail/iterator_to_raw_pointer.hpp
index 83736d8bb1..8c7c880035 100644
--- a/boost/container/detail/iterator_to_raw_pointer.hpp
+++ b/boost/container/detail/iterator_to_raw_pointer.hpp
@@ -18,38 +18,13 @@
# pragma once
#endif
-#include <boost/container/detail/iterator.hpp>
-#include <boost/container/detail/to_raw_pointer.hpp>
-#include <boost/intrusive/pointer_traits.hpp>
+#include <boost/move/detail/iterator_to_raw_pointer.hpp>
namespace boost {
namespace container {
namespace container_detail {
-template <class T>
-inline T* iterator_to_pointer(T* i)
-{ return i; }
-
-template <class Iterator>
-inline typename boost::container::iterator_traits<Iterator>::pointer
- iterator_to_pointer(const Iterator &i)
-{ return i.operator->(); }
-
-template <class Iterator>
-struct iterator_to_element_ptr
-{
- typedef typename boost::container::iterator_traits<Iterator>::pointer pointer;
- typedef typename boost::intrusive::pointer_traits<pointer>::element_type element_type;
- typedef element_type* type;
-};
-
-template <class Iterator>
-inline typename iterator_to_element_ptr<Iterator>::type
- iterator_to_raw_pointer(const Iterator &i)
-{
- return ::boost::intrusive::detail::to_raw_pointer
- ( ::boost::container::container_detail::iterator_to_pointer(i) );
-}
+using ::boost::movelib::iterator_to_raw_pointer;
} //namespace container_detail {
} //namespace container {
diff --git a/boost/container/detail/multiallocation_chain.hpp b/boost/container/detail/multiallocation_chain.hpp
index 32f87c8ae9..bce1b8651f 100644
--- a/boost/container/detail/multiallocation_chain.hpp
+++ b/boost/container/detail/multiallocation_chain.hpp
@@ -24,7 +24,7 @@
// container
#include <boost/container/container_fwd.hpp>
// container/detail
-#include <boost/container/detail/to_raw_pointer.hpp>
+#include <boost/move/detail/to_raw_pointer.hpp>
#include <boost/container/detail/transform_iterator.hpp>
#include <boost/container/detail/type_traits.hpp>
// intrusive
@@ -63,7 +63,7 @@ class basic_multiallocation_chain
pointer_traits<node_ptr> node_ptr_traits;
static node & to_node(const VoidPointer &p)
- { return *static_cast<node*>(static_cast<void*>(container_detail::to_raw_pointer(p))); }
+ { return *static_cast<node*>(static_cast<void*>(boost::movelib::to_raw_pointer(p))); }
static VoidPointer from_node(node &n)
{ return node_ptr_traits::pointer_to(n); }
@@ -152,7 +152,7 @@ class basic_multiallocation_chain
char_ptr prev_elem = elem;
elem += unit_bytes;
for(size_type i = 0; i != num_units-1; ++i, elem += unit_bytes){
- ::new (container_detail::to_raw_pointer(prev_elem)) void_pointer(elem);
+ ::new (boost::movelib::to_raw_pointer(prev_elem)) void_pointer(elem);
prev_elem = elem;
}
slist_impl_.incorporate_after(after_this, to_node_ptr(b), to_node_ptr(prev_elem), num_units);
diff --git a/boost/container/detail/node_alloc_holder.hpp b/boost/container/detail/node_alloc_holder.hpp
index 7ef5d2883e..b6e602e884 100644
--- a/boost/container/detail/node_alloc_holder.hpp
+++ b/boost/container/detail/node_alloc_holder.hpp
@@ -30,10 +30,10 @@
#include <boost/container/detail/allocator_version_traits.hpp>
#include <boost/container/detail/construct_in_place.hpp>
#include <boost/container/detail/destroyers.hpp>
-#include <boost/container/detail/iterator_to_raw_pointer.hpp>
+#include <boost/move/detail/iterator_to_raw_pointer.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/placement_new.hpp>
-#include <boost/container/detail/to_raw_pointer.hpp>
+#include <boost/move/detail/to_raw_pointer.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/version_type.hpp>
// intrusive
@@ -106,23 +106,23 @@ struct node_alloc_holder
: members_(a)
{}
+ //Constructors for associative containers
+ node_alloc_holder(const value_compare &c, const ValAlloc &a)
+ : members_(a, c)
+ {}
+
explicit node_alloc_holder(const node_alloc_holder &x)
: members_(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()))
{}
+ node_alloc_holder(const node_alloc_holder &x, const value_compare &c)
+ : members_(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()), c)
+ {}
+
explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x)
: members_(boost::move(x.node_alloc()))
{ this->icont().swap(x.icont()); }
- //Constructors for associative containers
- explicit node_alloc_holder(const value_compare &c, const ValAlloc &a)
- : members_(a, c)
- {}
-
- explicit node_alloc_holder(const value_compare &c, const node_alloc_holder &x)
- : members_(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()), c)
- {}
-
explicit node_alloc_holder(const value_compare &c)
: members_(c)
{}
@@ -171,7 +171,7 @@ struct node_alloc_holder
node_deallocator.release();
//This does not throw
typedef typename Node::hook_type hook_type;
- ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;
+ ::new(static_cast<hook_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type;
return (p);
}
@@ -189,7 +189,7 @@ struct node_alloc_holder
BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
node_deallocator.release();\
typedef typename Node::hook_type hook_type;\
- ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;\
+ ::new(static_cast<hook_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type;\
return (p);\
}\
//
@@ -207,7 +207,7 @@ struct node_alloc_holder
node_deallocator.release();
//This does not throw
typedef typename Node::hook_type hook_type;
- ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;
+ ::new(static_cast<hook_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type;
return (p);
}
@@ -230,13 +230,13 @@ struct node_alloc_holder
node_deallocator.release();
//This does not throw
typedef typename Node::hook_type hook_type;
- ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;
+ ::new(static_cast<hook_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type;
return (p);
}
void destroy_node(const NodePtr &nodep)
{
- allocator_traits<NodeAlloc>::destroy(this->node_alloc(), container_detail::to_raw_pointer(nodep));
+ allocator_traits<NodeAlloc>::destroy(this->node_alloc(), boost::movelib::to_raw_pointer(nodep));
this->deallocate_one(nodep);
}
@@ -266,7 +266,7 @@ struct node_alloc_holder
Deallocator node_deallocator(NodePtr(), nalloc);
container_detail::scoped_destructor<NodeAlloc> sdestructor(nalloc, 0);
while(n--){
- p = container_detail::iterator_to_raw_pointer(itbeg);
+ p = boost::movelib::iterator_to_raw_pointer(itbeg);
node_deallocator.set(p);
++itbeg;
//This can throw
diff --git a/boost/container/detail/node_pool_impl.hpp b/boost/container/detail/node_pool_impl.hpp
index 4febf19e90..024bf306c5 100644
--- a/boost/container/detail/node_pool_impl.hpp
+++ b/boost/container/detail/node_pool_impl.hpp
@@ -25,7 +25,7 @@
#include <boost/container/detail/math_functions.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/pool_common.hpp>
-#include <boost/container/detail/to_raw_pointer.hpp>
+#include <boost/move/detail/to_raw_pointer.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/intrusive/pointer_traits.hpp>
@@ -92,7 +92,7 @@ class private_node_pool_impl
//!Returns the segment manager. Never throws
segment_manager_base_type* get_segment_manager_base()const
- { return container_detail::to_raw_pointer(mp_segment_mngr_base); }
+ { return boost::movelib::to_raw_pointer(mp_segment_mngr_base); }
void *allocate_node()
{ return this->priv_alloc_node(); }
diff --git a/boost/container/detail/pair.hpp b/boost/container/detail/pair.hpp
index 4abff4b4d8..4755e569b2 100644
--- a/boost/container/detail/pair.hpp
+++ b/boost/container/detail/pair.hpp
@@ -35,16 +35,62 @@
#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
#include <boost/move/utility_core.hpp>
-#include<boost/move/detail/fwd_macros.hpp>
+#include <boost/move/detail/fwd_macros.hpp>
namespace boost {
namespace tuples {
struct null_type;
+template <
+ class T0, class T1, class T2,
+ class T3, class T4, class T5,
+ class T6, class T7, class T8,
+ class T9>
+class tuple;
+
} //namespace tuples {
} //namespace boost {
+namespace boost {
+namespace container {
+namespace pair_impl {
+
+template <class TupleClass>
+struct is_boost_tuple
+{
+ static const bool value = false;
+};
+
+template <
+ class T0, class T1, class T2,
+ class T3, class T4, class T5,
+ class T6, class T7, class T8,
+ class T9>
+struct is_boost_tuple< boost::tuples::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
+{
+ static const bool value = true;
+};
+
+template<class Tuple>
+struct disable_if_boost_tuple
+ : boost::container::container_detail::disable_if< is_boost_tuple<Tuple> >
+{};
+
+template<class T>
+struct is_tuple_null
+{
+ static const bool value = false;
+};
+
+template<>
+struct is_tuple_null<boost::tuples::null_type>
+{
+ static const bool value = true;
+};
+
+}}}
+
#if defined(BOOST_MSVC) && (_CPPLIB_VER == 520)
//MSVC 2010 tuple marker
namespace std { namespace tr1 { struct _Nil; }}
@@ -236,7 +282,12 @@ struct pair
BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
pair( piecewise_construct_t\
, BoostTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::boost::tuples::null_type)> p\
- , BoostTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::boost::tuples::null_type)> q)\
+ , BoostTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::boost::tuples::null_type)> q\
+ , typename container_detail::enable_if_c\
+ < pair_impl::is_boost_tuple< BoostTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::boost::tuples::null_type)> >::value &&\
+ !(pair_impl::is_tuple_null<BOOST_MOVE_LAST_TARG##N>::value || pair_impl::is_tuple_null<BOOST_MOVE_LAST_TARGQ##M>::value) \
+ >::type* = 0\
+ )\
: first(BOOST_MOVE_TMPL_GET##N), second(BOOST_MOVE_TMPL_GETQ##M)\
{ (void)p; (void)q; }\
//
@@ -254,7 +305,8 @@ struct pair
{ (void) t1; (void)t2; }
public:
- template<template<class ...> class Tuple, class... Args1, class... Args2>
+ template< template<class ...> class Tuple, class... Args1, class... Args2
+ , class = typename pair_impl::disable_if_boost_tuple< Tuple<Args1...> >::type>
pair(piecewise_construct_t, Tuple<Args1...> t1, Tuple<Args2...> t2)
: pair(t1, t2, typename build_number_seq<sizeof...(Args1)>::type(), typename build_number_seq<sizeof...(Args2)>::type())
{}
@@ -270,7 +322,8 @@ struct pair
{ (void)t; return T(::boost::forward<Args>(get<Indexes>(t))...); }
public:
- template<template<class ...> class Tuple, class... Args1, class... Args2>
+ template< template<class ...> class Tuple, class... Args1, class... Args2
+ , class = typename pair_impl::disable_if_boost_tuple< Tuple<Args1...> >::type>
pair(piecewise_construct_t, Tuple<Args1...> t1, Tuple<Args2...> t2)
: first (build_from_args<first_type> (::boost::move(t1)))
, second (build_from_args<second_type>(::boost::move(t2)))
diff --git a/boost/container/detail/pair_key_mapped_of_value.hpp b/boost/container/detail/pair_key_mapped_of_value.hpp
new file mode 100644
index 0000000000..6112b87826
--- /dev/null
+++ b/boost/container/detail/pair_key_mapped_of_value.hpp
@@ -0,0 +1,55 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_CONTAINER_PAIR_KEY_MAPPED_OF_VALUE_HPP
+#define BOOST_CONTAINER_PAIR_KEY_MAPPED_OF_VALUE_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+namespace boost {
+namespace container {
+
+template<class Key, class Mapped>
+struct pair_key_mapped_of_value
+{
+ typedef Key key_type;
+ typedef Mapped mapped_type;
+
+ template<class Pair>
+ const key_type & key_of_value(const Pair &p) const
+ { return p.first; }
+
+ template<class Pair>
+ const mapped_type & mapped_of_value(const Pair &p) const
+ { return p.second; }
+
+ template<class Pair>
+ key_type & key_of_value(Pair &p) const
+ { return const_cast<key_type&>(p.first); }
+
+ template<class Pair>
+ mapped_type & mapped_of_value(Pair &p) const
+ { return p.second; }
+
+};
+
+}}
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // BOOST_CONTAINER_PAIR_KEY_MAPPED_OF_VALUE_HPP
diff --git a/boost/container/detail/to_raw_pointer.hpp b/boost/container/detail/to_raw_pointer.hpp
deleted file mode 100644
index 0b4445a942..0000000000
--- a/boost/container/detail/to_raw_pointer.hpp
+++ /dev/null
@@ -1,33 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-//
-// (C) Copyright Ion Gaztanaga 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)
-//
-// See http://www.boost.org/libs/container for documentation.
-//
-//////////////////////////////////////////////////////////////////////////////
-#ifndef BOOST_CONTAINER_DETAIL_TO_RAW_POINTER_HPP
-#define BOOST_CONTAINER_DETAIL_TO_RAW_POINTER_HPP
-
-#ifndef BOOST_CONFIG_HPP
-# include <boost/config.hpp>
-#endif
-
-#if defined(BOOST_HAS_PRAGMA_ONCE)
-# pragma once
-#endif
-
-#include <boost/intrusive/detail/to_raw_pointer.hpp>
-
-namespace boost {
-namespace container {
-namespace container_detail {
-
-using ::boost::intrusive::detail::to_raw_pointer;
-
-} //namespace container_detail {
-} //namespace container {
-} //namespace boost {
-
-#endif //#ifndef BOOST_CONTAINER_DETAIL_TO_RAW_POINTER_HPP
diff --git a/boost/container/detail/tree.hpp b/boost/container/detail/tree.hpp
index 853d0ad843..99baf3a257 100644
--- a/boost/container/detail/tree.hpp
+++ b/boost/container/detail/tree.hpp
@@ -493,7 +493,7 @@ class tree
typedef boost::container::reverse_iterator
<const_iterator> const_reverse_iterator;
typedef node_handle
- < Node, value_type, allocator_type, void> node_type;
+ < NodeAlloc, void> node_type;
typedef insert_return_type_base
<iterator, node_type> insert_return_type;
@@ -509,7 +509,11 @@ class tree
: AllocHolder()
{}
- BOOST_CONTAINER_FORCEINLINE explicit tree(const key_compare& comp, const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE explicit tree(const key_compare& comp)
+ : AllocHolder(ValComp(comp))
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE explicit tree(const key_compare& comp, const allocator_type& a)
: AllocHolder(ValComp(comp), a)
{}
@@ -518,85 +522,110 @@ class tree
{}
template <class InputIterator>
- tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp,
- const allocator_type& a
- #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- , typename container_detail::enable_if_or
- < void
- , container_detail::is_same<alloc_version, version_1>
- , container_detail::is_input_iterator<InputIterator>
- >::type * = 0
- #endif
- )
+ tree(bool unique_insertion, InputIterator first, InputIterator last)
+ : AllocHolder(value_compare(key_compare()))
+ {
+ this->tree_construct(unique_insertion, first, last);
+ //AllocHolder clears in case of exception
+ }
+
+ template <class InputIterator>
+ tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp)
+ : AllocHolder(value_compare(comp))
+ {
+ this->tree_construct(unique_insertion, first, last);
+ //AllocHolder clears in case of exception
+ }
+
+ template <class InputIterator>
+ tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp, const allocator_type& a)
: AllocHolder(value_compare(comp), a)
{
+ this->tree_construct(unique_insertion, first, last);
+ //AllocHolder clears in case of exception
+ }
+
+ //construct with ordered range
+ template <class InputIterator>
+ tree( ordered_range_t, InputIterator first, InputIterator last)
+ : AllocHolder(value_compare(key_compare()))
+ {
+ this->tree_construct(ordered_range_t(), first, last);
+ }
+
+ template <class InputIterator>
+ tree( ordered_range_t, InputIterator first, InputIterator last, const key_compare& comp)
+ : AllocHolder(value_compare(comp))
+ {
+ this->tree_construct(ordered_range_t(), first, last);
+ }
+
+ template <class InputIterator>
+ tree( ordered_range_t, InputIterator first, InputIterator last
+ , const key_compare& comp, const allocator_type& a)
+ : AllocHolder(value_compare(comp), a)
+ {
+ this->tree_construct(ordered_range_t(), first, last);
+ }
+
+ private:
+
+ template <class InputIterator>
+ void tree_construct(bool unique_insertion, InputIterator first, InputIterator last)
+ {
//Use cend() as hint to achieve linear time for
//ordered ranges as required by the standard
//for the constructor
- const const_iterator end_it(this->cend());
if(unique_insertion){
+ const const_iterator end_it(this->cend());
for ( ; first != last; ++first){
this->insert_unique_convertible(end_it, *first);
}
}
else{
- for ( ; first != last; ++first){
- this->insert_equal_convertible(end_it, *first);
- }
+ this->tree_construct_non_unique(first, last);
}
}
template <class InputIterator>
- tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp,
- const allocator_type& a
+ void tree_construct_non_unique(InputIterator first, InputIterator last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- , typename container_detail::disable_if_or
+ , typename container_detail::enable_if_or
< void
, container_detail::is_same<alloc_version, version_1>
, container_detail::is_input_iterator<InputIterator>
>::type * = 0
#endif
)
- : AllocHolder(value_compare(comp), a)
{
- if(unique_insertion){
- //Use cend() as hint to achieve linear time for
- //ordered ranges as required by the standard
- //for the constructor
- const const_iterator end_it(this->cend());
- for ( ; first != last; ++first){
- this->insert_unique_convertible(end_it, *first);
- }
- }
- else{
- //Optimized allocation and construction
- this->allocate_many_and_construct
- ( first, boost::container::iterator_distance(first, last)
- , insert_equal_end_hint_functor<Node, Icont>(this->icont()));
+ //Use cend() as hint to achieve linear time for
+ //ordered ranges as required by the standard
+ //for the constructor
+ const const_iterator end_it(this->cend());
+ for ( ; first != last; ++first){
+ this->insert_equal_convertible(end_it, *first);
}
}
template <class InputIterator>
- tree( ordered_range_t, InputIterator first, InputIterator last
- , const key_compare& comp = key_compare(), const allocator_type& a = allocator_type()
- #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- , typename container_detail::enable_if_or
+ void tree_construct_non_unique(InputIterator first, InputIterator last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::disable_if_or
< void
, container_detail::is_same<alloc_version, version_1>
, container_detail::is_input_iterator<InputIterator>
>::type * = 0
- #endif
+ #endif
)
- : AllocHolder(value_compare(comp), a)
{
- for ( ; first != last; ++first){
- this->push_back_impl(*first);
- }
+ //Optimized allocation and construction
+ this->allocate_many_and_construct
+ ( first, boost::container::iterator_distance(first, last)
+ , insert_equal_end_hint_functor<Node, Icont>(this->icont()));
}
template <class InputIterator>
- tree( ordered_range_t, InputIterator first, InputIterator last
- , const key_compare& comp = key_compare(), const allocator_type& a = allocator_type()
+ void tree_construct( ordered_range_t, InputIterator first, InputIterator last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::disable_if_or
< void
@@ -605,16 +634,34 @@ class tree
>::type * = 0
#endif
)
- : AllocHolder(value_compare(comp), a)
{
//Optimized allocation and construction
this->allocate_many_and_construct
( first, boost::container::iterator_distance(first, last)
, container_detail::push_back_functor<Node, Icont>(this->icont()));
+ //AllocHolder clears in case of exception
+ }
+
+ template <class InputIterator>
+ void tree_construct( ordered_range_t, InputIterator first, InputIterator last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_or
+ < void
+ , container_detail::is_same<alloc_version, version_1>
+ , container_detail::is_input_iterator<InputIterator>
+ >::type * = 0
+ #endif
+ )
+ {
+ for ( ; first != last; ++first){
+ this->push_back_impl(*first);
+ }
}
+ public:
+
BOOST_CONTAINER_FORCEINLINE tree(const tree& x)
- : AllocHolder(x.value_comp(), x)
+ : AllocHolder(x, x.value_comp())
{
this->icont().clone_from
(x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc()));
@@ -630,6 +677,7 @@ class tree
{
this->icont().clone_from
(x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc()));
+ //AllocHolder clears in case of exception
}
tree(BOOST_RV_REF(tree) x, const allocator_type &a)
@@ -642,6 +690,7 @@ class tree
this->icont().clone_from
(boost::move(x.icont()), typename AllocHolder::move_cloner(*this), Destroyer(this->node_alloc()));
}
+ //AllocHolder clears in case of exception
}
BOOST_CONTAINER_FORCEINLINE ~tree()
@@ -1142,7 +1191,7 @@ class tree
this->insert_unique_check(hint, KeyOfValue()(nh.value()), data);
if(ret.second){
irt.inserted = true;
- irt.position = iterator(this->icont().insert_unique_commit(*nh.get_node_pointer(), data));
+ irt.position = iterator(this->icont().insert_unique_commit(*nh.get(), data));
nh.release();
}
else{
diff --git a/boost/container/flat_map.hpp b/boost/container/flat_map.hpp
index b842101feb..56f12ecbe8 100644
--- a/boost/container/flat_map.hpp
+++ b/boost/container/flat_map.hpp
@@ -59,14 +59,15 @@ class flat_multimap;
namespace container_detail{
template<class D, class S>
-BOOST_CONTAINER_FORCEINLINE static D &force(const S &s)
-{ return *const_cast<D*>((reinterpret_cast<const D*>(&s))); }
+BOOST_CONTAINER_FORCEINLINE static D &force(S &s)
+{ return *reinterpret_cast<D*>(&s); }
template<class D, class S>
-BOOST_CONTAINER_FORCEINLINE static D force_copy(S s)
+BOOST_CONTAINER_FORCEINLINE static D force_copy(const S &s)
{
- D *vp = reinterpret_cast<D *>(&s);
- return D(*vp);
+ const D *const vp = reinterpret_cast<const D *>(&s);
+ D ret_val(*vp);
+ return ret_val;
}
} //namespace container_detail{
@@ -144,13 +145,15 @@ class flat_map
<typename allocator_traits<Allocator>::pointer>::reverse_iterator reverse_iterator_impl;
typedef typename container_detail::get_flat_tree_iterators
<typename allocator_traits<Allocator>::pointer>::const_reverse_iterator const_reverse_iterator_impl;
+
public:
typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type;
+ typedef typename impl_tree_t::sequence_type impl_sequence_type;
- impl_tree_t &tree()
+ BOOST_CONTAINER_FORCEINLINE impl_tree_t &tree()
{ return m_flat_tree; }
- const impl_tree_t &tree() const
+ BOOST_CONTAINER_FORCEINLINE const impl_tree_t &tree() const
{ return m_flat_tree; }
private:
@@ -182,8 +185,11 @@ class flat_map
typedef BOOST_CONTAINER_IMPDEF(reverse_iterator_impl) reverse_iterator;
typedef BOOST_CONTAINER_IMPDEF(const_reverse_iterator_impl) const_reverse_iterator;
typedef BOOST_CONTAINER_IMPDEF(impl_value_type) movable_value_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_type;
+
+ //Allocator::value_type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- public:
//////////////////////////////////////////////
//
// construct/copy/destroy
@@ -193,106 +199,183 @@ class flat_map
//! <b>Effects</b>: Default constructs an empty flat_map.
//!
//! <b>Complexity</b>: Constant.
- flat_map() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
- container_detail::is_nothrow_default_constructible<Compare>::value)
+ flat_map() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
+ container_detail::is_nothrow_default_constructible<Compare>::value)
: m_flat_tree()
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE explicit flat_map(const allocator_type& a)
+ : m_flat_tree(container_detail::force<const impl_allocator_type>(a))
+ {}
//! <b>Effects</b>: Constructs an empty flat_map using the specified
- //! comparison object and allocator.
+ //! comparison object.
//!
//! <b>Complexity</b>: Constant.
- explicit flat_map(const Compare& comp, const allocator_type& a = allocator_type())
- : m_flat_tree(comp, container_detail::force<impl_allocator_type>(a))
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ BOOST_CONTAINER_FORCEINLINE explicit flat_map(const Compare& comp)
+ : m_flat_tree(comp)
+ {}
- //! <b>Effects</b>: Constructs an empty flat_map using the specified allocator.
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified
+ //! comparison object and allocator.
//!
//! <b>Complexity</b>: Constant.
- explicit flat_map(const allocator_type& a)
- : m_flat_tree(container_detail::force<impl_allocator_type>(a))
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ BOOST_CONTAINER_FORCEINLINE flat_map(const Compare& comp, const allocator_type& a)
+ : m_flat_tree(comp, container_detail::force<const impl_allocator_type>(a))
+ {}
- //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
- //! allocator, and inserts elements from the range [first ,last ).
+ //! <b>Effects</b>: Constructs an empty flat_map and
+ //! and inserts elements from the range [first ,last ).
//!
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
- //! comp and otherwise N logN, where N is last - first.
+ //! the predicate and otherwise N logN, where N is last - first.
template <class InputIterator>
- flat_map(InputIterator first, InputIterator last, const Compare& comp = Compare(),
- const allocator_type& a = allocator_type())
- : m_flat_tree(true, first, last, comp, container_detail::force<impl_allocator_type>(a))
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ BOOST_CONTAINER_FORCEINLINE flat_map(InputIterator first, InputIterator last)
+ : m_flat_tree(true, first, last)
+ {}
//! <b>Effects</b>: Constructs an empty flat_map using the specified
//! allocator, and inserts elements from the range [first ,last ).
//!
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
- //! comp and otherwise N logN, where N is last - first.
+ //! the predicate and otherwise N logN, where N is last - first.
template <class InputIterator>
- flat_map(InputIterator first, InputIterator last, const allocator_type& a)
- : m_flat_tree(true, first, last, Compare(), container_detail::force<impl_allocator_type>(a))
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ BOOST_CONTAINER_FORCEINLINE flat_map(InputIterator first, InputIterator last, const allocator_type& a)
+ : m_flat_tree(true, first, last, container_detail::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE flat_map(InputIterator first, InputIterator last, const Compare& comp)
+ : m_flat_tree(true, first, last, comp)
+ {}
//! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
- //! allocator, and inserts elements from the ordered unique range [first ,last). This function
+ //! allocator, and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE flat_map(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : m_flat_tree(true, first, last, comp, container_detail::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map
+ //! and inserts elements from the ordered range [first ,last). This function
//! is more efficient than the normal range creation for ordered ranges.
//!
- //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be
- //! unique values.
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
//!
//! <b>Complexity</b>: Linear in N.
//!
//! <b>Note</b>: Non-standard extension.
template <class InputIterator>
- flat_map( ordered_unique_range_t, InputIterator first, InputIterator last
- , const Compare& comp = Compare(), const allocator_type& a = allocator_type())
- : m_flat_tree(ordered_unique_range, first, last, comp, a)
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ BOOST_CONTAINER_FORCEINLINE
+ flat_map(ordered_unique_range_t, InputIterator first, InputIterator last)
+ : m_flat_tree(ordered_range, first, last)
+ {}
-#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
- //! allocator, and inserts elements from the range [il.begin() ,il.end()).
+ //! inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_map(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : m_flat_tree(ordered_range, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! allocator, and inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_map(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : m_flat_tree(ordered_range, first, last, comp, a)
+ {}
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs an empty flat_map and
+ //! inserts elements from the range [il.begin() ,il.end()).
//!
//! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
- //! comp and otherwise N logN, where N is last - first.
- flat_map(std::initializer_list<value_type> il, const Compare& comp = Compare(),
- const allocator_type& a = allocator_type())
- : m_flat_tree(true, il.begin(), il.end(), comp, container_detail::force<impl_allocator_type>(a))
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il)
+ : m_flat_tree(true, il.begin(), il.end())
+ {}
//! <b>Effects</b>: Constructs an empty flat_map using the specified
//! allocator, and inserts elements from the range [il.begin() ,il.end()).
//!
//! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
- //! comp and otherwise N logN, where N is last - first.
- flat_map(std::initializer_list<value_type> il, const allocator_type& a)
- : m_flat_tree(true, il.begin(), il.end(), Compare(), container_detail::force<impl_allocator_type>(a))
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il, const allocator_type& a)
+ : m_flat_tree(true, il.begin(), il.end(), container_detail::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! inserts elements from the range [il.begin() ,il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il, const Compare& comp)
+ : m_flat_tree(true, il.begin(), il.end(), comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! allocator, and inserts elements from the range [il.begin() ,il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : m_flat_tree(true, il.begin(), il.end(), comp, container_detail::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using and
+ //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE flat_map(ordered_unique_range_t, std::initializer_list<value_type> il)
+ : m_flat_tree(ordered_unique_range, il.begin(), il.end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE flat_map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp)
+ : m_flat_tree(ordered_unique_range, il.begin(), il.end(), comp)
+ {}
//! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
//! allocator, and inserts elements from the ordered unique range [il.begin(), il.end()). This function
@@ -304,24 +387,17 @@ class flat_map
//! <b>Complexity</b>: Linear in N.
//!
//! <b>Note</b>: Non-standard extension.
- flat_map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(),
- const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE flat_map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
: m_flat_tree(ordered_unique_range, il.begin(), il.end(), comp, a)
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ {}
#endif
//! <b>Effects</b>: Copy constructs a flat_map.
//!
//! <b>Complexity</b>: Linear in x.size().
- flat_map(const flat_map& x)
+ BOOST_CONTAINER_FORCEINLINE flat_map(const flat_map& x)
: m_flat_tree(x.m_flat_tree)
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ {}
//! <b>Effects</b>: Move constructs a flat_map.
//! Constructs *this using x's resources.
@@ -329,39 +405,30 @@ class flat_map
//! <b>Complexity</b>: Constant.
//!
//! <b>Postcondition</b>: x is emptied.
- flat_map(BOOST_RV_REF(flat_map) x)
+ BOOST_CONTAINER_FORCEINLINE flat_map(BOOST_RV_REF(flat_map) x)
BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value)
: m_flat_tree(boost::move(x.m_flat_tree))
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ {}
//! <b>Effects</b>: Copy constructs a flat_map using the specified allocator.
//!
//! <b>Complexity</b>: Linear in x.size().
- flat_map(const flat_map& x, const allocator_type &a)
+ BOOST_CONTAINER_FORCEINLINE flat_map(const flat_map& x, const allocator_type &a)
: m_flat_tree(x.m_flat_tree, a)
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ {}
//! <b>Effects</b>: Move constructs a flat_map using the specified allocator.
//! Constructs *this using x's resources.
//!
//! <b>Complexity</b>: Constant if x.get_allocator() == a, linear otherwise.
- flat_map(BOOST_RV_REF(flat_map) x, const allocator_type &a)
+ BOOST_CONTAINER_FORCEINLINE flat_map(BOOST_RV_REF(flat_map) x, const allocator_type &a)
: m_flat_tree(boost::move(x.m_flat_tree), a)
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ {}
//! <b>Effects</b>: Makes *this a copy of x.
//!
//! <b>Complexity</b>: Linear in x.size().
- flat_map& operator=(BOOST_COPY_ASSIGN_REF(flat_map) x)
+ BOOST_CONTAINER_FORCEINLINE flat_map& operator=(BOOST_COPY_ASSIGN_REF(flat_map) x)
{ m_flat_tree = x.m_flat_tree; return *this; }
//! <b>Effects</b>: Move constructs a flat_map.
@@ -373,7 +440,7 @@ class flat_map
//! <b>Complexity</b>: Constant if allocator_traits_type::
//! propagate_on_container_move_assignment is true or
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
- flat_map& operator=(BOOST_RV_REF(flat_map) x)
+ BOOST_CONTAINER_FORCEINLINE flat_map& operator=(BOOST_RV_REF(flat_map) x)
BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
allocator_traits_type::is_always_equal::value) &&
boost::container::container_detail::is_nothrow_move_assignable<Compare>::value)
@@ -393,7 +460,7 @@ class flat_map
//! was passed to the object's constructor.
//!
//! <b>Complexity</b>: Constant.
- allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<allocator_type>(m_flat_tree.get_allocator()); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
@@ -403,7 +470,7 @@ class flat_map
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
- stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
@@ -413,8 +480,8 @@ class flat_map
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
- const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
- { return container_detail::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
+ BOOST_CONTAINER_FORCEINLINE const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return container_detail::force<const stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
//////////////////////////////////////////////
//
@@ -427,7 +494,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<iterator>(m_flat_tree.begin()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
@@ -435,7 +502,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<const_iterator>(m_flat_tree.begin()); }
//! <b>Effects</b>: Returns an iterator to the end of the container.
@@ -443,7 +510,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- iterator end() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE iterator end() BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<iterator>(m_flat_tree.end()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
@@ -451,7 +518,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<const_iterator>(m_flat_tree.end()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
@@ -460,7 +527,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<reverse_iterator>(m_flat_tree.rbegin()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -469,7 +536,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.rbegin()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
@@ -478,7 +545,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<reverse_iterator>(m_flat_tree.rend()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -487,7 +554,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.rend()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
@@ -495,7 +562,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<const_iterator>(m_flat_tree.cbegin()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
@@ -503,7 +570,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<const_iterator>(m_flat_tree.cend()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -512,7 +579,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.crbegin()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -521,7 +588,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.crend()); }
//////////////////////////////////////////////
@@ -535,7 +602,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
{ return m_flat_tree.empty(); }
//! <b>Effects</b>: Returns the number of the elements contained in the container.
@@ -543,7 +610,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
{ return m_flat_tree.size(); }
//! <b>Effects</b>: Returns the largest possible size of the container.
@@ -551,7 +618,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
{ return m_flat_tree.max_size(); }
//! <b>Effects</b>: Number of elements for which memory has been allocated.
@@ -560,7 +627,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
{ return m_flat_tree.capacity(); }
//! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
@@ -572,7 +639,7 @@ class flat_map
//!
//! <b>Note</b>: If capacity() is less than "cnt", iterators and references to
//! to values might be invalidated.
- void reserve(size_type cnt)
+ BOOST_CONTAINER_FORCEINLINE void reserve(size_type cnt)
{ m_flat_tree.reserve(cnt); }
//! <b>Effects</b>: Tries to deallocate the excess of memory created
@@ -581,7 +648,7 @@ class flat_map
//! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
//!
//! <b>Complexity</b>: Linear to size().
- void shrink_to_fit()
+ BOOST_CONTAINER_FORCEINLINE void shrink_to_fit()
{ m_flat_tree.shrink_to_fit(); }
//////////////////////////////////////////////
@@ -608,8 +675,8 @@ class flat_map
mapped_type &operator[](key_type &&k) ;
#elif defined(BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN)
//in compilers like GCC 3.4, we can't catch temporaries
- mapped_type& operator[](const key_type &k) { return this->priv_subscript(k); }
- mapped_type& operator[](BOOST_RV_REF(key_type) k) { return this->priv_subscript(::boost::move(k)); }
+ BOOST_CONTAINER_FORCEINLINE mapped_type& operator[](const key_type &k) { return this->priv_subscript(k); }
+ BOOST_CONTAINER_FORCEINLINE mapped_type& operator[](BOOST_RV_REF(key_type) k) { return this->priv_subscript(::boost::move(k)); }
#else
BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, this->priv_subscript)
#endif
@@ -705,19 +772,19 @@ class flat_map
}
//! @copydoc ::boost::container::flat_set::nth(size_type)
- iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<iterator>(m_flat_tree.nth(n)); }
//! @copydoc ::boost::container::flat_set::nth(size_type) const
- const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<iterator>(m_flat_tree.nth(n)); }
//! @copydoc ::boost::container::flat_set::index_of(iterator)
- size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
{ return m_flat_tree.index_of(container_detail::force_copy<impl_iterator>(p)); }
//! @copydoc ::boost::container::flat_set::index_of(const_iterator) const
- size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
{ return m_flat_tree.index_of(container_detail::force_copy<impl_const_iterator>(p)); }
//! Returns: A reference to the element whose key is equivalent to x.
@@ -769,7 +836,7 @@ class flat_map
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class... Args>
- std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args)
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args)
{ return container_detail::force_copy< std::pair<iterator, bool> >(m_flat_tree.emplace_unique(boost::forward<Args>(args)...)); }
//! <b>Effects</b>: Inserts an object of type T constructed with
@@ -785,7 +852,7 @@ class flat_map
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class... Args>
- iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
{
return container_detail::force_copy<iterator>
(m_flat_tree.emplace_hint_unique( container_detail::force_copy<impl_const_iterator>(hint)
@@ -869,14 +936,14 @@ class flat_map
#define BOOST_CONTAINER_FLAT_MAP_EMPLACE_CODE(N) \
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
- std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\
{\
return container_detail::force_copy< std::pair<iterator, bool> >\
(m_flat_tree.emplace_unique(BOOST_MOVE_FWD##N));\
}\
\
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
- iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{\
return container_detail::force_copy<iterator>(m_flat_tree.emplace_hint_unique\
(container_detail::force_copy<impl_const_iterator>(hint) BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
@@ -921,9 +988,9 @@ class flat_map
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- std::pair<iterator,bool> insert(const value_type& x)
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(const value_type& x)
{ return container_detail::force_copy<std::pair<iterator,bool> >(
- m_flat_tree.insert_unique(container_detail::force<impl_value_type>(x))); }
+ m_flat_tree.insert_unique(container_detail::force<const impl_value_type>(x))); }
//! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
//! only if there is no element in the container with key equivalent to the key of x.
@@ -936,7 +1003,7 @@ class flat_map
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x)
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x)
{ return container_detail::force_copy<std::pair<iterator,bool> >(
m_flat_tree.insert_unique(boost::move(container_detail::force<impl_value_type>(x)))); }
@@ -951,7 +1018,7 @@ class flat_map
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- std::pair<iterator,bool> insert(BOOST_RV_REF(movable_value_type) x)
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(movable_value_type) x)
{
return container_detail::force_copy<std::pair<iterator,bool> >
(m_flat_tree.insert_unique(boost::move(x)));
@@ -968,11 +1035,11 @@ class flat_map
//! right before p) plus insertion linear to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- iterator insert(const_iterator p, const value_type& x)
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const value_type& x)
{
return container_detail::force_copy<iterator>(
m_flat_tree.insert_unique( container_detail::force_copy<impl_const_iterator>(p)
- , container_detail::force<impl_value_type>(x)));
+ , container_detail::force<const impl_value_type>(x)));
}
//! <b>Effects</b>: Inserts an element move constructed from x in the container.
@@ -984,7 +1051,7 @@ class flat_map
//! right before p) plus insertion linear to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- iterator insert(const_iterator p, BOOST_RV_REF(value_type) x)
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(value_type) x)
{
return container_detail::force_copy<iterator>
(m_flat_tree.insert_unique( container_detail::force_copy<impl_const_iterator>(p)
@@ -1000,7 +1067,7 @@ class flat_map
//! right before p) plus insertion linear to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x)
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x)
{
return container_detail::force_copy<iterator>(
m_flat_tree.insert_unique(container_detail::force_copy<impl_const_iterator>(p), boost::move(x)));
@@ -1016,7 +1083,7 @@ class flat_map
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class InputIterator>
- void insert(InputIterator first, InputIterator last)
+ BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
{ m_flat_tree.insert_unique(first, last); }
//! <b>Requires</b>: first, last are not iterators into *this.
@@ -1035,7 +1102,7 @@ class flat_map
//!
//! <b>Note</b>: Non-standard extension.
template <class InputIterator>
- void insert(ordered_unique_range_t, InputIterator first, InputIterator last)
+ BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, InputIterator first, InputIterator last)
{ m_flat_tree.insert_unique(ordered_unique_range, first, last); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@@ -1046,7 +1113,7 @@ class flat_map
//! search time plus N*size() insertion time.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- void insert(std::initializer_list<value_type> il)
+ BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
{ m_flat_tree.insert_unique(il.begin(), il.end()); }
//! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
@@ -1062,7 +1129,7 @@ class flat_map
//! <b>Note</b>: If an element is inserted it might invalidate elements.
//!
//! <b>Note</b>: Non-standard extension.
- void insert(ordered_unique_range_t, std::initializer_list<value_type> il)
+ BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, std::initializer_list<value_type> il)
{ m_flat_tree.insert_unique(ordered_unique_range, il.begin(), il.end()); }
#endif
@@ -1109,7 +1176,7 @@ class flat_map
//!
//! <b>Note</b>: Invalidates elements with keys
//! not less than the erased element.
- iterator erase(const_iterator p)
+ BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator p)
{
return container_detail::force_copy<iterator>
(m_flat_tree.erase(container_detail::force_copy<impl_const_iterator>(p)));
@@ -1121,7 +1188,7 @@ class flat_map
//!
//! <b>Complexity</b>: Logarithmic search time plus erasure time
//! linear to the elements with bigger keys.
- size_type erase(const key_type& x)
+ BOOST_CONTAINER_FORCEINLINE size_type erase(const key_type& x)
{ return m_flat_tree.erase(x); }
//! <b>Effects</b>: Erases all the elements in the range [first, last).
@@ -1132,7 +1199,7 @@ class flat_map
//!
//! <b>Complexity</b>: Logarithmic search time plus erasure time
//! linear to the elements with bigger keys.
- iterator erase(const_iterator first, const_iterator last)
+ BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator first, const_iterator last)
{
return container_detail::force_copy<iterator>(
m_flat_tree.erase( container_detail::force_copy<impl_const_iterator>(first)
@@ -1144,7 +1211,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- void swap(flat_map& x)
+ BOOST_CONTAINER_FORCEINLINE void swap(flat_map& x)
BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
&& boost::container::container_detail::is_nothrow_swappable<Compare>::value )
{ m_flat_tree.swap(x.m_flat_tree); }
@@ -1154,7 +1221,7 @@ class flat_map
//! <b>Postcondition</b>: size() == 0.
//!
//! <b>Complexity</b>: linear in size().
- void clear() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE void clear() BOOST_NOEXCEPT_OR_NOTHROW
{ m_flat_tree.clear(); }
//////////////////////////////////////////////
@@ -1167,14 +1234,14 @@ class flat_map
//! of which a was constructed.
//!
//! <b>Complexity</b>: Constant.
- key_compare key_comp() const
+ BOOST_CONTAINER_FORCEINLINE key_compare key_comp() const
{ return container_detail::force_copy<key_compare>(m_flat_tree.key_comp()); }
//! <b>Effects</b>: Returns an object of value_compare constructed out
//! of the comparison object.
//!
//! <b>Complexity</b>: Constant.
- value_compare value_comp() const
+ BOOST_CONTAINER_FORCEINLINE value_compare value_comp() const
{ return value_compare(container_detail::force_copy<key_compare>(m_flat_tree.key_comp())); }
//////////////////////////////////////////////
@@ -1187,102 +1254,135 @@ class flat_map
//! equivalent to x, or end() if such an element is not found.
//!
//! <b>Complexity</b>: Logarithmic.
- iterator find(const key_type& x)
+ BOOST_CONTAINER_FORCEINLINE iterator find(const key_type& x)
{ return container_detail::force_copy<iterator>(m_flat_tree.find(x)); }
//! <b>Returns</b>: A const_iterator pointing to an element with the key
//! equivalent to x, or end() if such an element is not found.
//!
//! <b>Complexity</b>: Logarithmic.
- const_iterator find(const key_type& x) const
+ BOOST_CONTAINER_FORCEINLINE const_iterator find(const key_type& x) const
{ return container_detail::force_copy<const_iterator>(m_flat_tree.find(x)); }
//! <b>Returns</b>: The number of elements with key equivalent to x.
//!
//! <b>Complexity</b>: log(size())+count(k)
- size_type count(const key_type& x) const
+ BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const
{ return static_cast<size_type>(m_flat_tree.find(x) != m_flat_tree.end()); }
//! <b>Returns</b>: An iterator pointing to the first element with key not less
//! than k, or a.end() if such an element is not found.
//!
//! <b>Complexity</b>: Logarithmic.
- iterator lower_bound(const key_type& x)
+ BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const key_type& x)
{ return container_detail::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
//! <b>Returns</b>: A const iterator pointing to the first element with key not
//! less than k, or a.end() if such an element is not found.
//!
//! <b>Complexity</b>: Logarithmic.
- const_iterator lower_bound(const key_type& x) const
+ BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const key_type& x) const
{ return container_detail::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
//! <b>Returns</b>: An iterator pointing to the first element with key not less
//! than x, or end() if such an element is not found.
//!
//! <b>Complexity</b>: Logarithmic.
- iterator upper_bound(const key_type& x)
+ BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const key_type& x)
{ return container_detail::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
//! <b>Returns</b>: A const iterator pointing to the first element with key not
//! less than x, or end() if such an element is not found.
//!
//! <b>Complexity</b>: Logarithmic.
- const_iterator upper_bound(const key_type& x) const
+ BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const key_type& x) const
{ return container_detail::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic.
- std::pair<iterator,iterator> equal_range(const key_type& x)
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const key_type& x)
{ return container_detail::force_copy<std::pair<iterator,iterator> >(m_flat_tree.lower_bound_range(x)); }
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic.
- std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const
+ BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
{ return container_detail::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.lower_bound_range(x)); }
+ //! <b>Effects</b>: Extracts the internal sequence container.
+ //!
+ //! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant.
+ //!
+ //! <b>Postcondition</b>: this->empty()
+ //!
+ //! <b>Throws</b>: If secuence_type's move constructor throws
+ BOOST_CONTAINER_FORCEINLINE sequence_type extract_sequence()
+ {
+ return boost::move(container_detail::force<sequence_type>(m_flat_tree.get_sequence_ref()));
+ }
+
+ //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
+ //! one passed externally using the move assignment. Erases non-unique elements.
+ //!
+ //! <b>Complexity</b>: Assuming O(1) move assignment, O(NlogN) with N = seq.size()
+ //!
+ //! <b>Throws</b>: If the comparison or the move constructor throws
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence(BOOST_RV_REF(sequence_type) seq)
+ { this->m_flat_tree.adopt_sequence_unique(boost::move(container_detail::force<impl_sequence_type>(seq))); }
+
+ //! <b>Requires</b>: seq shall be ordered according to this->compare()
+ //! and shall contain unique elements.
+ //!
+ //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
+ //! one passed externally using the move assignment.
+ //!
+ //! <b>Complexity</b>: Assuming O(1) move assignment, O(1)
+ //!
+ //! <b>Throws</b>: If the move assignment throws
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_unique_range_t, BOOST_RV_REF(sequence_type) seq)
+ { this->m_flat_tree.adopt_sequence_unique(ordered_unique_range_t(), boost::move(container_detail::force<impl_sequence_type>(seq))); }
+
//! <b>Effects</b>: Returns true if x and y are equal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
- friend bool operator==(const flat_map& x, const flat_map& y)
+ BOOST_CONTAINER_FORCEINLINE friend bool operator==(const flat_map& x, const flat_map& y)
{ return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
//! <b>Effects</b>: Returns true if x and y are unequal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
- friend bool operator!=(const flat_map& x, const flat_map& y)
+ BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const flat_map& x, const flat_map& y)
{ return !(x == y); }
//! <b>Effects</b>: Returns true if x is less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
- friend bool operator<(const flat_map& x, const flat_map& y)
+ BOOST_CONTAINER_FORCEINLINE friend bool operator<(const flat_map& x, const flat_map& y)
{ return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
//! <b>Effects</b>: Returns true if x is greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
- friend bool operator>(const flat_map& x, const flat_map& y)
+ BOOST_CONTAINER_FORCEINLINE friend bool operator>(const flat_map& x, const flat_map& y)
{ return y < x; }
//! <b>Effects</b>: Returns true if x is equal or less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
- friend bool operator<=(const flat_map& x, const flat_map& y)
+ BOOST_CONTAINER_FORCEINLINE friend bool operator<=(const flat_map& x, const flat_map& y)
{ return !(y < x); }
//! <b>Effects</b>: Returns true if x is equal or greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
- friend bool operator>=(const flat_map& x, const flat_map& y)
+ BOOST_CONTAINER_FORCEINLINE friend bool operator>=(const flat_map& x, const flat_map& y)
{ return !(x < y); }
//! <b>Effects</b>: x.swap(y)
//!
//! <b>Complexity</b>: Constant.
- friend void swap(flat_map& x, flat_map& y)
+ BOOST_CONTAINER_FORCEINLINE friend void swap(flat_map& x, flat_map& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -1401,11 +1501,12 @@ class flat_multimap
<typename allocator_traits<Allocator>::pointer>::const_reverse_iterator const_reverse_iterator_impl;
public:
typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type;
+ typedef typename impl_tree_t::sequence_type impl_sequence_type;
- impl_tree_t &tree()
+ BOOST_CONTAINER_FORCEINLINE impl_tree_t &tree()
{ return m_flat_tree; }
- const impl_tree_t &tree() const
+ BOOST_CONTAINER_FORCEINLINE const impl_tree_t &tree() const
{ return m_flat_tree; }
private:
@@ -1437,6 +1538,10 @@ class flat_multimap
typedef BOOST_CONTAINER_IMPDEF(reverse_iterator_impl) reverse_iterator;
typedef BOOST_CONTAINER_IMPDEF(const_reverse_iterator_impl) const_reverse_iterator;
typedef BOOST_CONTAINER_IMPDEF(impl_value_type) movable_value_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_type;
+
+ //Allocator::value_type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
//////////////////////////////////////////////
//
@@ -1447,63 +1552,109 @@ class flat_multimap
//! <b>Effects</b>: Default constructs an empty flat_map.
//!
//! <b>Complexity</b>: Constant.
- flat_multimap() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
- container_detail::is_nothrow_default_constructible<Compare>::value)
+ BOOST_CONTAINER_FORCEINLINE flat_multimap()
+ BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
+ container_detail::is_nothrow_default_constructible<Compare>::value)
: m_flat_tree()
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE explicit flat_multimap(const allocator_type& a)
+ : m_flat_tree(container_detail::force<const impl_allocator_type>(a))
+ {}
//! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison
- //! object and allocator.
+ //! object .
//!
//! <b>Complexity</b>: Constant.
- explicit flat_multimap(const Compare& comp,
- const allocator_type& a = allocator_type())
- : m_flat_tree(comp, container_detail::force<impl_allocator_type>(a))
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ BOOST_CONTAINER_FORCEINLINE explicit flat_multimap(const Compare& comp)
+ : m_flat_tree(comp)
+ {}
- //! <b>Effects</b>: Constructs an empty flat_multimap using the specified allocator.
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison
+ //! object and allocator.
//!
//! <b>Complexity</b>: Constant.
- explicit flat_multimap(const allocator_type& a)
- : m_flat_tree(container_detail::force<impl_allocator_type>(a))
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(const Compare& comp, const allocator_type& a)
+ : m_flat_tree(comp, container_detail::force<const impl_allocator_type>(a))
+ {}
- //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object
- //! and allocator, and inserts elements from the range [first ,last ).
+ //! <b>Effects</b>: Constructs an empty flat_multimap
+ //! and inserts elements from the range [first ,last ).
//!
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
- //! comp and otherwise N logN, where N is last - first.
+ //! the predicate and otherwise N logN, where N is last - first.
template <class InputIterator>
- flat_multimap(InputIterator first, InputIterator last,
- const Compare& comp = Compare(),
- const allocator_type& a = allocator_type())
- : m_flat_tree(false, first, last, comp, container_detail::force<impl_allocator_type>(a))
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(InputIterator first, InputIterator last)
+ : m_flat_tree(false, first, last)
+ {}
//! <b>Effects</b>: Constructs an empty flat_multimap using the specified
//! allocator, and inserts elements from the range [first ,last ).
//!
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
- //! comp and otherwise N logN, where N is last - first.
+ //! the predicate and otherwise N logN, where N is last - first.
template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
flat_multimap(InputIterator first, InputIterator last, const allocator_type& a)
- : m_flat_tree(false, first, last, Compare(), container_detail::force<impl_allocator_type>(a))
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ : m_flat_tree(false, first, last, container_detail::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object
+ //! and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(InputIterator first, InputIterator last, const Compare& comp)
+ : m_flat_tree(false, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object
+ //! and allocator, and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : m_flat_tree(false, first, last, comp, container_detail::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap
+ //! and inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(ordered_range_t, InputIterator first, InputIterator last)
+ : m_flat_tree(ordered_range, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
+ //! inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : m_flat_tree(ordered_range, first, last, comp)
+ {}
//! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
//! allocator, and inserts elements from the ordered range [first ,last). This function
@@ -1515,39 +1666,79 @@ class flat_multimap
//!
//! <b>Note</b>: Non-standard extension.
template <class InputIterator>
- flat_multimap(ordered_range_t, InputIterator first, InputIterator last,
- const Compare& comp = Compare(),
- const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
: m_flat_tree(ordered_range, first, last, comp, a)
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ {}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
- //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
- //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //! <b>Effects</b>: Constructs an empty flat_map and
+ //! inserts elements from the range [il.begin(), il.end()).
//!
//! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
- //! comp and otherwise N logN, where N is last - first.
- flat_multimap(std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type())
- : m_flat_tree(false, il.begin(), il.end(), comp, container_detail::force<impl_allocator_type>(a))
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(std::initializer_list<value_type> il)
+ : m_flat_tree(false, il.begin(), il.end())
+ {}
//! <b>Effects</b>: Constructs an empty flat_map using the specified
//! allocator, and inserts elements from the range [il.begin(), il.end()).
//!
//! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
- //! comp and otherwise N logN, where N is last - first.
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE
flat_multimap(std::initializer_list<value_type> il, const allocator_type& a)
- : m_flat_tree(false, il.begin(), il.end(), Compare(), container_detail::force<impl_allocator_type>(a))
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ : m_flat_tree(false, il.begin(), il.end(), container_detail::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(std::initializer_list<value_type> il, const Compare& comp)
+ : m_flat_tree(false, il.begin(), il.end(), comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : m_flat_tree(false, il.begin(), il.end(), comp, container_detail::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap and
+ //! inserts elements from the ordered range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(ordered_range_t, std::initializer_list<value_type> il)
+ : m_flat_tree(ordered_range, il.begin(), il.end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
+ //! inserts elements from the ordered range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp)
+ : m_flat_tree(ordered_range, il.begin(), il.end(), comp)
+ {}
//! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
//! allocator, and inserts elements from the ordered range [il.begin(), il.end()). This function
@@ -1558,68 +1749,59 @@ class flat_multimap
//! <b>Complexity</b>: Linear in N.
//!
//! <b>Note</b>: Non-standard extension.
- flat_multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(),
- const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
: m_flat_tree(ordered_range, il.begin(), il.end(), comp, a)
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ {}
#endif
//! <b>Effects</b>: Copy constructs a flat_multimap.
//!
//! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE
flat_multimap(const flat_multimap& x)
: m_flat_tree(x.m_flat_tree)
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ {}
//! <b>Effects</b>: Move constructs a flat_multimap. Constructs *this using x's resources.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Postcondition</b>: x is emptied.
+ BOOST_CONTAINER_FORCEINLINE
flat_multimap(BOOST_RV_REF(flat_multimap) x)
BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value)
: m_flat_tree(boost::move(x.m_flat_tree))
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ {}
//! <b>Effects</b>: Copy constructs a flat_multimap using the specified allocator.
//!
//! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE
flat_multimap(const flat_multimap& x, const allocator_type &a)
: m_flat_tree(x.m_flat_tree, a)
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ {}
//! <b>Effects</b>: Move constructs a flat_multimap using the specified allocator.
//! Constructs *this using x's resources.
//!
//! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
+ BOOST_CONTAINER_FORCEINLINE
flat_multimap(BOOST_RV_REF(flat_multimap) x, const allocator_type &a)
: m_flat_tree(boost::move(x.m_flat_tree), a)
- {
- //value_type must be std::pair<Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
- }
+ {}
//! <b>Effects</b>: Makes *this a copy of x.
//!
//! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE
flat_multimap& operator=(BOOST_COPY_ASSIGN_REF(flat_multimap) x)
{ m_flat_tree = x.m_flat_tree; return *this; }
//! <b>Effects</b>: this->swap(x.get()).
//!
//! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
flat_multimap& operator=(BOOST_RV_REF(flat_multimap) x)
BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
allocator_traits_type::is_always_equal::value) &&
@@ -1630,6 +1812,7 @@ class flat_multimap
//! <b>Effects</b>: Assign content of il to *this
//!
//! <b>Complexity</b>: Linear in il.size().
+ BOOST_CONTAINER_FORCEINLINE
flat_multimap& operator=(std::initializer_list<value_type> il)
{
this->clear();
@@ -1642,6 +1825,7 @@ class flat_multimap
//! was passed to the object's constructor.
//!
//! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<allocator_type>(m_flat_tree.get_allocator()); }
@@ -1652,6 +1836,7 @@ class flat_multimap
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE
stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
@@ -1662,8 +1847,9 @@ class flat_multimap
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE
const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
- { return container_detail::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
+ { return container_detail::force<const stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
//////////////////////////////////////////////
//
@@ -1676,6 +1862,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<iterator>(m_flat_tree.begin()); }
@@ -1684,6 +1871,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<const_iterator>(m_flat_tree.begin()); }
@@ -1692,6 +1880,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
iterator end() BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<iterator>(m_flat_tree.end()); }
@@ -1700,6 +1889,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<const_iterator>(m_flat_tree.end()); }
@@ -1709,6 +1899,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<reverse_iterator>(m_flat_tree.rbegin()); }
@@ -1718,6 +1909,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.rbegin()); }
@@ -1727,6 +1919,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<reverse_iterator>(m_flat_tree.rend()); }
@@ -1736,6 +1929,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.rend()); }
@@ -1744,6 +1938,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<const_iterator>(m_flat_tree.cbegin()); }
@@ -1752,6 +1947,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<const_iterator>(m_flat_tree.cend()); }
@@ -1761,6 +1957,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.crbegin()); }
@@ -1770,6 +1967,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.crend()); }
@@ -1784,6 +1982,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
{ return m_flat_tree.empty(); }
@@ -1792,6 +1991,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
{ return m_flat_tree.size(); }
@@ -1800,6 +2000,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
{ return m_flat_tree.max_size(); }
@@ -1809,6 +2010,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
{ return m_flat_tree.capacity(); }
@@ -1821,6 +2023,7 @@ class flat_multimap
//!
//! <b>Note</b>: If capacity() is less than "cnt", iterators and references to
//! to values might be invalidated.
+ BOOST_CONTAINER_FORCEINLINE
void reserve(size_type cnt)
{ m_flat_tree.reserve(cnt); }
@@ -1830,22 +2033,27 @@ class flat_multimap
//! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
//!
//! <b>Complexity</b>: Linear to size().
+ BOOST_CONTAINER_FORCEINLINE
void shrink_to_fit()
{ m_flat_tree.shrink_to_fit(); }
//! @copydoc ::boost::container::flat_set::nth(size_type)
+ BOOST_CONTAINER_FORCEINLINE
iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<iterator>(m_flat_tree.nth(n)); }
//! @copydoc ::boost::container::flat_set::nth(size_type) const
+ BOOST_CONTAINER_FORCEINLINE
const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::force_copy<iterator>(m_flat_tree.nth(n)); }
//! @copydoc ::boost::container::flat_set::index_of(iterator)
+ BOOST_CONTAINER_FORCEINLINE
size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
{ return m_flat_tree.index_of(container_detail::force_copy<impl_iterator>(p)); }
//! @copydoc ::boost::container::flat_set::index_of(const_iterator) const
+ BOOST_CONTAINER_FORCEINLINE
size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
{ return m_flat_tree.index_of(container_detail::force_copy<impl_const_iterator>(p)); }
@@ -1860,6 +2068,7 @@ class flat_multimap
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE
iterator emplace(BOOST_FWD_REF(Args)... args)
{ return container_detail::force_copy<iterator>(m_flat_tree.emplace_equal(boost::forward<Args>(args)...)); }
@@ -1876,6 +2085,7 @@ class flat_multimap
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
{
return container_detail::force_copy<iterator>(m_flat_tree.emplace_hint_equal
@@ -1886,11 +2096,11 @@ class flat_multimap
#define BOOST_CONTAINER_FLAT_MULTIMAP_EMPLACE_CODE(N) \
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
- iterator emplace(BOOST_MOVE_UREF##N)\
+ BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_MOVE_UREF##N)\
{ return container_detail::force_copy<iterator>(m_flat_tree.emplace_equal(BOOST_MOVE_FWD##N)); }\
\
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
- iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{\
return container_detail::force_copy<iterator>(m_flat_tree.emplace_hint_equal\
(container_detail::force_copy<impl_const_iterator>(hint) BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
@@ -1908,10 +2118,10 @@ class flat_multimap
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- iterator insert(const value_type& x)
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const value_type& x)
{
return container_detail::force_copy<iterator>(
- m_flat_tree.insert_equal(container_detail::force<impl_value_type>(x)));
+ m_flat_tree.insert_equal(container_detail::force<const impl_value_type>(x)));
}
//! <b>Effects</b>: Inserts a new value move-constructed from x and returns
@@ -1921,7 +2131,7 @@ class flat_multimap
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- iterator insert(BOOST_RV_REF(value_type) x)
+ BOOST_CONTAINER_FORCEINLINE iterator insert(BOOST_RV_REF(value_type) x)
{ return container_detail::force_copy<iterator>(m_flat_tree.insert_equal(boost::move(x))); }
//! <b>Effects</b>: Inserts a new value move-constructed from x and returns
@@ -1931,7 +2141,7 @@ class flat_multimap
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- iterator insert(BOOST_RV_REF(impl_value_type) x)
+ BOOST_CONTAINER_FORCEINLINE iterator insert(BOOST_RV_REF(impl_value_type) x)
{ return container_detail::force_copy<iterator>(m_flat_tree.insert_equal(boost::move(x))); }
//! <b>Effects</b>: Inserts a copy of x in the container.
@@ -1945,11 +2155,11 @@ class flat_multimap
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- iterator insert(const_iterator p, const value_type& x)
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const value_type& x)
{
return container_detail::force_copy<iterator>
(m_flat_tree.insert_equal( container_detail::force_copy<impl_const_iterator>(p)
- , container_detail::force<impl_value_type>(x)));
+ , container_detail::force<const impl_value_type>(x)));
}
//! <b>Effects</b>: Inserts a value move constructed from x in the container.
@@ -1963,7 +2173,7 @@ class flat_multimap
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- iterator insert(const_iterator p, BOOST_RV_REF(value_type) x)
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(value_type) x)
{
return container_detail::force_copy<iterator>
(m_flat_tree.insert_equal(container_detail::force_copy<impl_const_iterator>(p)
@@ -1981,7 +2191,7 @@ class flat_multimap
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- iterator insert(const_iterator p, BOOST_RV_REF(impl_value_type) x)
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(impl_value_type) x)
{
return container_detail::force_copy<iterator>(
m_flat_tree.insert_equal(container_detail::force_copy<impl_const_iterator>(p), boost::move(x)));
@@ -1996,7 +2206,7 @@ class flat_multimap
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class InputIterator>
- void insert(InputIterator first, InputIterator last)
+ BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
{ m_flat_tree.insert_equal(first, last); }
//! <b>Requires</b>: first, last are not iterators into *this.
@@ -2014,7 +2224,7 @@ class flat_multimap
//!
//! <b>Note</b>: Non-standard extension.
template <class InputIterator>
- void insert(ordered_range_t, InputIterator first, InputIterator last)
+ BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, InputIterator first, InputIterator last)
{ m_flat_tree.insert_equal(ordered_range, first, last); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@@ -2024,7 +2234,7 @@ class flat_multimap
//! search time plus N*size() insertion time.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- void insert(std::initializer_list<value_type> il)
+ BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
{ m_flat_tree.insert_equal(il.begin(), il.end()); }
//! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
@@ -2039,7 +2249,7 @@ class flat_multimap
//! <b>Note</b>: If an element is inserted it might invalidate elements.
//!
//! <b>Note</b>: Non-standard extension.
- void insert(ordered_range_t, std::initializer_list<value_type> il)
+ BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, std::initializer_list<value_type> il)
{ m_flat_tree.insert_equal(ordered_range, il.begin(), il.end()); }
#endif
@@ -2057,22 +2267,22 @@ class flat_multimap
//!
//! <b>Complexity</b>: N log(a.size() + N) (N has the value source.size())
template<class C2>
- void merge(flat_multimap<Key, T, C2, Allocator>& source)
+ BOOST_CONTAINER_FORCEINLINE void merge(flat_multimap<Key, T, C2, Allocator>& source)
{ m_flat_tree.merge_equal(source.tree()); }
//! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, Allocator>&)
template<class C2>
- void merge(BOOST_RV_REF_BEG flat_multimap<Key, T, C2, Allocator> BOOST_RV_REF_END source)
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multimap<Key, T, C2, Allocator> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_multimap<Key, T, C2, Allocator>&>(source)); }
//! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, Allocator>&)
template<class C2>
- void merge(flat_map<Key, T, C2, Allocator>& source)
+ BOOST_CONTAINER_FORCEINLINE void merge(flat_map<Key, T, C2, Allocator>& source)
{ m_flat_tree.merge_equal(source.tree()); }
- //! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, Allocator>&)
+ //! @copydoc ::boost::container::flat_multimap::merge(flat_map<Key, T, C2, Allocator>&)
template<class C2>
- void merge(BOOST_RV_REF_BEG flat_map<Key, T, C2, Allocator> BOOST_RV_REF_END source)
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_map<Key, T, C2, Allocator> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_map<Key, T, C2, Allocator>&>(source)); }
//! <b>Effects</b>: Erases the element pointed to by p.
@@ -2085,7 +2295,7 @@ class flat_multimap
//!
//! <b>Note</b>: Invalidates elements with keys
//! not less than the erased element.
- iterator erase(const_iterator p)
+ BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator p)
{
return container_detail::force_copy<iterator>(
m_flat_tree.erase(container_detail::force_copy<impl_const_iterator>(p)));
@@ -2097,7 +2307,7 @@ class flat_multimap
//!
//! <b>Complexity</b>: Logarithmic search time plus erasure time
//! linear to the elements with bigger keys.
- size_type erase(const key_type& x)
+ BOOST_CONTAINER_FORCEINLINE size_type erase(const key_type& x)
{ return m_flat_tree.erase(x); }
//! <b>Effects</b>: Erases all the elements in the range [first, last).
@@ -2108,7 +2318,7 @@ class flat_multimap
//!
//! <b>Complexity</b>: Logarithmic search time plus erasure time
//! linear to the elements with bigger keys.
- iterator erase(const_iterator first, const_iterator last)
+ BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator first, const_iterator last)
{
return container_detail::force_copy<iterator>
(m_flat_tree.erase( container_detail::force_copy<impl_const_iterator>(first)
@@ -2120,7 +2330,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- void swap(flat_multimap& x)
+ BOOST_CONTAINER_FORCEINLINE void swap(flat_multimap& x)
BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
&& boost::container::container_detail::is_nothrow_swappable<Compare>::value )
{ m_flat_tree.swap(x.m_flat_tree); }
@@ -2130,7 +2340,7 @@ class flat_multimap
//! <b>Postcondition</b>: size() == 0.
//!
//! <b>Complexity</b>: linear in size().
- void clear() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE void clear() BOOST_NOEXCEPT_OR_NOTHROW
{ m_flat_tree.clear(); }
//////////////////////////////////////////////
@@ -2143,14 +2353,14 @@ class flat_multimap
//! of which a was constructed.
//!
//! <b>Complexity</b>: Constant.
- key_compare key_comp() const
+ BOOST_CONTAINER_FORCEINLINE key_compare key_comp() const
{ return container_detail::force_copy<key_compare>(m_flat_tree.key_comp()); }
//! <b>Effects</b>: Returns an object of value_compare constructed out
//! of the comparison object.
//!
//! <b>Complexity</b>: Constant.
- value_compare value_comp() const
+ BOOST_CONTAINER_FORCEINLINE value_compare value_comp() const
{ return value_compare(container_detail::force_copy<key_compare>(m_flat_tree.key_comp())); }
//////////////////////////////////////////////
@@ -2163,102 +2373,134 @@ class flat_multimap
//! equivalent to x, or end() if such an element is not found.
//!
//! <b>Complexity</b>: Logarithmic.
- iterator find(const key_type& x)
+ BOOST_CONTAINER_FORCEINLINE iterator find(const key_type& x)
{ return container_detail::force_copy<iterator>(m_flat_tree.find(x)); }
//! <b>Returns</b>: An const_iterator pointing to an element with the key
//! equivalent to x, or end() if such an element is not found.
//!
//! <b>Complexity</b>: Logarithmic.
- const_iterator find(const key_type& x) const
+ BOOST_CONTAINER_FORCEINLINE const_iterator find(const key_type& x) const
{ return container_detail::force_copy<const_iterator>(m_flat_tree.find(x)); }
//! <b>Returns</b>: The number of elements with key equivalent to x.
//!
//! <b>Complexity</b>: log(size())+count(k)
- size_type count(const key_type& x) const
+ BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const
{ return m_flat_tree.count(x); }
//! <b>Returns</b>: An iterator pointing to the first element with key not less
//! than k, or a.end() if such an element is not found.
//!
//! <b>Complexity</b>: Logarithmic
- iterator lower_bound(const key_type& x)
+ BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const key_type& x)
{ return container_detail::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
//! <b>Returns</b>: A const iterator pointing to the first element with key
//! not less than k, or a.end() if such an element is not found.
//!
//! <b>Complexity</b>: Logarithmic
- const_iterator lower_bound(const key_type& x) const
+ BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const key_type& x) const
{ return container_detail::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
//! <b>Returns</b>: An iterator pointing to the first element with key not less
//! than x, or end() if such an element is not found.
//!
//! <b>Complexity</b>: Logarithmic
- iterator upper_bound(const key_type& x)
+ BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const key_type& x)
{return container_detail::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
//! <b>Returns</b>: A const iterator pointing to the first element with key
//! not less than x, or end() if such an element is not found.
//!
//! <b>Complexity</b>: Logarithmic
- const_iterator upper_bound(const key_type& x) const
+ BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const key_type& x) const
{ return container_detail::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
- std::pair<iterator,iterator> equal_range(const key_type& x)
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const key_type& x)
{ return container_detail::force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
- std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const
+ BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
{ return container_detail::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
+ //! <b>Effects</b>: Extracts the internal sequence container.
+ //!
+ //! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant.
+ //!
+ //! <b>Postcondition</b>: this->empty()
+ //!
+ //! <b>Throws</b>: If secuence_type's move constructor throws
+ BOOST_CONTAINER_FORCEINLINE sequence_type extract_sequence()
+ {
+ return boost::move(container_detail::force<sequence_type>(m_flat_tree.get_sequence_ref()));
+ }
+
+ //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
+ //! one passed externally using the move assignment.
+ //!
+ //! <b>Complexity</b>: Assuming O(1) move assignment, O(NlogN) with N = seq.size()
+ //!
+ //! <b>Throws</b>: If the comparison or the move constructor throws
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence(BOOST_RV_REF(sequence_type) seq)
+ { this->m_flat_tree.adopt_sequence_equal(boost::move(container_detail::force<impl_sequence_type>(seq))); }
+
+ //! <b>Requires</b>: seq shall be ordered according to this->compare().
+ //!
+ //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
+ //! one passed externally using the move assignment.
+ //!
+ //! <b>Complexity</b>: Assuming O(1) move assignment, O(1)
+ //!
+ //! <b>Throws</b>: If the move assignment throws
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_range_t, BOOST_RV_REF(sequence_type) seq)
+ { this->m_flat_tree.adopt_sequence_equal(ordered_range_t(), boost::move(container_detail::force<impl_sequence_type>(seq))); }
+
//! <b>Effects</b>: Returns true if x and y are equal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
- friend bool operator==(const flat_multimap& x, const flat_multimap& y)
+ BOOST_CONTAINER_FORCEINLINE friend bool operator==(const flat_multimap& x, const flat_multimap& y)
{ return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
//! <b>Effects</b>: Returns true if x and y are unequal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
- friend bool operator!=(const flat_multimap& x, const flat_multimap& y)
+ BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const flat_multimap& x, const flat_multimap& y)
{ return !(x == y); }
//! <b>Effects</b>: Returns true if x is less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
- friend bool operator<(const flat_multimap& x, const flat_multimap& y)
+ BOOST_CONTAINER_FORCEINLINE friend bool operator<(const flat_multimap& x, const flat_multimap& y)
{ return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
//! <b>Effects</b>: Returns true if x is greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
- friend bool operator>(const flat_multimap& x, const flat_multimap& y)
+ BOOST_CONTAINER_FORCEINLINE friend bool operator>(const flat_multimap& x, const flat_multimap& y)
{ return y < x; }
//! <b>Effects</b>: Returns true if x is equal or less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
- friend bool operator<=(const flat_multimap& x, const flat_multimap& y)
+ BOOST_CONTAINER_FORCEINLINE friend bool operator<=(const flat_multimap& x, const flat_multimap& y)
{ return !(y < x); }
//! <b>Effects</b>: Returns true if x is equal or greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
- friend bool operator>=(const flat_multimap& x, const flat_multimap& y)
+ BOOST_CONTAINER_FORCEINLINE friend bool operator>=(const flat_multimap& x, const flat_multimap& y)
{ return !(x < y); }
//! <b>Effects</b>: x.swap(y)
//!
//! <b>Complexity</b>: Constant.
- friend void swap(flat_multimap& x, flat_multimap& y)
+ BOOST_CONTAINER_FORCEINLINE friend void swap(flat_multimap& x, flat_multimap& y)
{ x.swap(y); }
};
diff --git a/boost/container/flat_set.hpp b/boost/container/flat_set.hpp
index fa27006177..9e39be8e78 100644
--- a/boost/container/flat_set.hpp
+++ b/boost/container/flat_set.hpp
@@ -114,6 +114,7 @@ class flat_set
typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_iterator) const_iterator;
typedef typename BOOST_CONTAINER_IMPDEF(base_t::reverse_iterator) reverse_iterator;
typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_reverse_iterator) const_reverse_iterator;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::sequence_type) sequence_type;
public:
//////////////////////////////////////////////
@@ -125,37 +126,47 @@ class flat_set
//! <b>Effects</b>: Default constructs an empty container.
//!
//! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
explicit flat_set() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
container_detail::is_nothrow_default_constructible<Compare>::value)
: base_t()
{}
//! <b>Effects</b>: Constructs an empty container using the specified
- //! comparison object and allocator.
+ //! comparison object.
//!
//! <b>Complexity</b>: Constant.
- explicit flat_set(const Compare& comp,
- const allocator_type& a = allocator_type())
- : base_t(comp, a)
+ BOOST_CONTAINER_FORCEINLINE
+ explicit flat_set(const Compare& comp)
+ : base_t(comp)
{}
//! <b>Effects</b>: Constructs an empty container using the specified allocator.
//!
//! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
explicit flat_set(const allocator_type& a)
: base_t(a)
{}
- //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
- //! allocator, and inserts elements from the range [first ,last ).
+ //! <b>Effects</b>: Constructs an empty container using the specified
+ //! comparison object and allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_set(const Compare& comp, const allocator_type& a)
+ : base_t(comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container and
+ //! inserts elements from the range [first ,last ).
//!
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
//! comp and otherwise N logN, where N is last - first.
template <class InputIterator>
- flat_set(InputIterator first, InputIterator last,
- const Compare& comp = Compare(),
- const allocator_type& a = allocator_type())
- : base_t(true, first, last, comp, a)
+ BOOST_CONTAINER_FORCEINLINE
+ flat_set(InputIterator first, InputIterator last)
+ : base_t(true, first, last)
{}
//! <b>Effects</b>: Constructs an empty container using the specified
@@ -164,8 +175,63 @@ class flat_set
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
//! comp and otherwise N logN, where N is last - first.
template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
flat_set(InputIterator first, InputIterator last, const allocator_type& a)
- : base_t(true, first, last, Compare(), a)
+ : base_t(true, first, last, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
+ //! inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! comp and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_set(InputIterator first, InputIterator last, const Compare& comp)
+ : base_t(true, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
+ //! allocator, and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! comp and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_set(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : base_t(true, first, last, comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container and
+ //! inserts elements from the ordered unique range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_set(ordered_unique_range_t, InputIterator first, InputIterator last)
+ : base_t(ordered_unique_range, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
+ //! inserts elements from the ordered unique range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_set(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : base_t(ordered_unique_range, first, last, comp)
{}
//! <b>Effects</b>: Constructs an empty container using the specified comparison object and
@@ -179,21 +245,19 @@ class flat_set
//!
//! <b>Note</b>: Non-standard extension.
template <class InputIterator>
- flat_set(ordered_unique_range_t, InputIterator first, InputIterator last,
- const Compare& comp = Compare(),
- const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE
+ flat_set(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
: base_t(ordered_unique_range, first, last, comp, a)
{}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
- //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
- //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //! <b>Effects</b>: Constructs an empty container and
+ //! inserts elements from the range [il.begin(), il.end()).
//!
//! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
//! comp and otherwise N logN, where N is il.begin() - il.end().
- flat_set(std::initializer_list<value_type> il, const Compare& comp = Compare(),
- const allocator_type& a = allocator_type())
- : base_t(true, il.begin(), il.end(), comp, a)
+ BOOST_CONTAINER_FORCEINLINE flat_set(std::initializer_list<value_type> il)
+ : base_t(true, il.begin(), il.end())
{}
//! <b>Effects</b>: Constructs an empty container using the specified
@@ -201,8 +265,54 @@ class flat_set
//!
//! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
//! comp and otherwise N logN, where N is il.begin() - il.end().
- flat_set(std::initializer_list<value_type> il, const allocator_type& a)
- : base_t(true, il.begin(), il.end(), Compare(), a)
+ BOOST_CONTAINER_FORCEINLINE flat_set(std::initializer_list<value_type> il, const allocator_type& a)
+ : base_t(true, il.begin(), il.end(), a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
+ //! inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! comp and otherwise N logN, where N is il.begin() - il.end().
+ BOOST_CONTAINER_FORCEINLINE flat_set(std::initializer_list<value_type> il, const Compare& comp)
+ : base_t(true, il.begin(), il.end(), comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
+ //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! comp and otherwise N logN, where N is il.begin() - il.end().
+ BOOST_CONTAINER_FORCEINLINE flat_set(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : base_t(true, il.begin(), il.end(), comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
+ //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE flat_set(ordered_unique_range_t, std::initializer_list<value_type> il)
+ : base_t(ordered_unique_range, il.begin(), il.end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
+ //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE flat_set(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp)
+ : base_t(ordered_unique_range, il.begin(), il.end(), comp)
{}
//! <b>Effects</b>: Constructs an empty container using the specified comparison object and
@@ -215,8 +325,7 @@ class flat_set
//! <b>Complexity</b>: Linear in N.
//!
//! <b>Note</b>: Non-standard extension.
- flat_set(ordered_unique_range_t, std::initializer_list<value_type> il,
- const Compare& comp = Compare(), const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE flat_set(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
: base_t(ordered_unique_range, il.begin(), il.end(), comp, a)
{}
#endif
@@ -224,7 +333,7 @@ class flat_set
//! <b>Effects</b>: Copy constructs the container.
//!
//! <b>Complexity</b>: Linear in x.size().
- flat_set(const flat_set& x)
+ BOOST_CONTAINER_FORCEINLINE flat_set(const flat_set& x)
: base_t(static_cast<const base_t&>(x))
{}
@@ -233,7 +342,7 @@ class flat_set
//! <b>Complexity</b>: Constant.
//!
//! <b>Postcondition</b>: x is emptied.
- flat_set(BOOST_RV_REF(flat_set) x)
+ BOOST_CONTAINER_FORCEINLINE flat_set(BOOST_RV_REF(flat_set) x)
BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value)
: base_t(BOOST_MOVE_BASE(base_t, x))
{}
@@ -241,7 +350,7 @@ class flat_set
//! <b>Effects</b>: Copy constructs a container using the specified allocator.
//!
//! <b>Complexity</b>: Linear in x.size().
- flat_set(const flat_set& x, const allocator_type &a)
+ BOOST_CONTAINER_FORCEINLINE flat_set(const flat_set& x, const allocator_type &a)
: base_t(static_cast<const base_t&>(x), a)
{}
@@ -249,14 +358,14 @@ class flat_set
//! Constructs *this using x's resources.
//!
//! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise
- flat_set(BOOST_RV_REF(flat_set) x, const allocator_type &a)
+ BOOST_CONTAINER_FORCEINLINE flat_set(BOOST_RV_REF(flat_set) x, const allocator_type &a)
: base_t(BOOST_MOVE_BASE(base_t, x), a)
{}
//! <b>Effects</b>: Makes *this a copy of x.
//!
//! <b>Complexity</b>: Linear in x.size().
- flat_set& operator=(BOOST_COPY_ASSIGN_REF(flat_set) x)
+ BOOST_CONTAINER_FORCEINLINE flat_set& operator=(BOOST_COPY_ASSIGN_REF(flat_set) x)
{ return static_cast<flat_set&>(this->base_t::operator=(static_cast<const base_t&>(x))); }
//! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
@@ -265,7 +374,7 @@ class flat_set
//! <b>Complexity</b>: Constant if allocator_traits_type::
//! propagate_on_container_move_assignment is true or
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
- flat_set& operator=(BOOST_RV_REF(flat_set) x)
+ BOOST_CONTAINER_FORCEINLINE flat_set& operator=(BOOST_RV_REF(flat_set) x)
BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
allocator_traits_type::is_always_equal::value) &&
boost::container::container_detail::is_nothrow_move_assignable<Compare>::value)
@@ -469,7 +578,7 @@ class flat_set
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class... Args>
- std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args)
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args)
{ return this->base_t::emplace_unique(boost::forward<Args>(args)...); }
//! <b>Effects</b>: Inserts an object of type Key constructed with
@@ -485,18 +594,18 @@ class flat_set
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class... Args>
- iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args)
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args)
{ return this->base_t::emplace_hint_unique(p, boost::forward<Args>(args)...); }
#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_CONTAINER_FLAT_SET_EMPLACE_CODE(N) \
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
- std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\
{ return this->base_t::emplace_unique(BOOST_MOVE_FWD##N); }\
\
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
- iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{ return this->base_t::emplace_hint_unique(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
//
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_FLAT_SET_EMPLACE_CODE)
@@ -575,7 +684,7 @@ class flat_set
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class InputIterator>
- void insert(InputIterator first, InputIterator last)
+ BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
{ this->base_t::insert_unique(first, last); }
//! <b>Requires</b>: first, last are not iterators into *this and
@@ -590,7 +699,7 @@ class flat_set
//!
//! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
template <class InputIterator>
- void insert(ordered_unique_range_t, InputIterator first, InputIterator last)
+ BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, InputIterator first, InputIterator last)
{ this->base_t::insert_unique(ordered_unique_range, first, last); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@@ -601,7 +710,7 @@ class flat_set
//! search time plus N*size() insertion time.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- void insert(std::initializer_list<value_type> il)
+ BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
{ this->base_t::insert_unique(il.begin(), il.end()); }
//! <b>Requires</b>: Range [il.begin(), il.end()) must be ordered according to the predicate
@@ -614,7 +723,7 @@ class flat_set
//! search time plus N*size() insertion time.
//!
//! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
- void insert(ordered_unique_range_t, std::initializer_list<value_type> il)
+ BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, std::initializer_list<value_type> il)
{ this->base_t::insert_unique(ordered_unique_range, il.begin(), il.end()); }
#endif
@@ -623,7 +732,7 @@ class flat_set
BOOST_CONTAINER_FORCEINLINE void merge(flat_set<Key, C2, Allocator>& source)
{ this->base_t::merge_unique(source.tree()); }
- //! @copydoc ::boost::container::flat_map::merge(flat_set<Key, C2, Allocator>&)
+ //! @copydoc ::boost::container::flat_set::merge(flat_set<Key, C2, Allocator>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_set<Key, C2, Allocator> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_set<Key, C2, Allocator>&>(source)); }
@@ -633,7 +742,7 @@ class flat_set
BOOST_CONTAINER_FORCEINLINE void merge(flat_multiset<Key, C2, Allocator>& source)
{ this->base_t::merge_unique(source.tree()); }
- //! @copydoc ::boost::container::flat_map::merge(flat_multiset<Key, C2, Allocator>&)
+ //! @copydoc ::boost::container::flat_set::merge(flat_multiset<Key, C2, Allocator>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multiset<Key, C2, Allocator> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_multiset<Key, C2, Allocator>&>(source)); }
@@ -765,7 +874,7 @@ class flat_set
//! <b>Returns</b>: The number of elements with key equivalent to x.
//!
//! <b>Complexity</b>: log(size())+count(k)
- size_type count(const key_type& x) const
+ BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const
{ return static_cast<size_type>(this->base_t::find(x) != this->base_t::cend()); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -798,13 +907,13 @@ class flat_set
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
- std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
+ BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
{ return this->base_t::lower_bound_range(x); }
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
- std::pair<iterator,iterator> equal_range(const key_type& x)
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const key_type& x)
{ return this->base_t::lower_bound_range(x); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -844,16 +953,46 @@ class flat_set
//! <b>Complexity</b>: Constant.
friend void swap(flat_set& x, flat_set& y);
+ //! <b>Effects</b>: Extracts the internal sequence container.
+ //!
+ //! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant.
+ //!
+ //! <b>Postcondition</b>: this->empty()
+ //!
+ //! <b>Throws</b>: If secuence_type's move constructor throws
+ sequence_type extract_sequence();
+
#endif //#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+ //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
+ //! one passed externally using the move assignment. Erases non-unique elements.
+ //!
+ //! <b>Complexity</b>: Assuming O(1) move assignment, O(NlogN) with N = seq.size()
+ //!
+ //! <b>Throws</b>: If the comparison or the move constructor throws
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence(BOOST_RV_REF(sequence_type) seq)
+ { this->base_t::adopt_sequence_unique(boost::move(seq)); }
+
+ //! <b>Requires</b>: seq shall be ordered according to this->compare()
+ //! and shall contain unique elements.
+ //!
+ //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
+ //! one passed externally using the move assignment.
+ //!
+ //! <b>Complexity</b>: Assuming O(1) move assignment, O(1)
+ //!
+ //! <b>Throws</b>: If the move assignment throws
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_unique_range_t, BOOST_RV_REF(sequence_type) seq)
+ { this->base_t::adopt_sequence_unique(ordered_unique_range_t(), boost::move(seq)); }
+
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
template<class KeyType>
- std::pair<iterator, bool> priv_insert(BOOST_FWD_REF(KeyType) x)
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> priv_insert(BOOST_FWD_REF(KeyType) x)
{ return this->base_t::insert_unique(::boost::forward<KeyType>(x)); }
template<class KeyType>
- iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
+ BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
{ return this->base_t::insert_unique(p, ::boost::forward<KeyType>(x)); }
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
@@ -939,40 +1078,83 @@ class flat_multiset
typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_iterator) const_iterator;
typedef typename BOOST_CONTAINER_IMPDEF(base_t::reverse_iterator) reverse_iterator;
typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_reverse_iterator) const_reverse_iterator;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::sequence_type) sequence_type;
//! @copydoc ::boost::container::flat_set::flat_set()
- explicit flat_multiset() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
+ BOOST_CONTAINER_FORCEINLINE explicit flat_multiset() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
container_detail::is_nothrow_default_constructible<Compare>::value)
: base_t()
{}
- //! @copydoc ::boost::container::flat_set::flat_set(const Compare&, const allocator_type&)
- explicit flat_multiset(const Compare& comp,
- const allocator_type& a = allocator_type())
- : base_t(comp, a)
+ //! @copydoc ::boost::container::flat_set::flat_set(const Compare&)
+ BOOST_CONTAINER_FORCEINLINE explicit flat_multiset(const Compare& comp)
+ : base_t(comp)
{}
//! @copydoc ::boost::container::flat_set::flat_set(const allocator_type&)
- explicit flat_multiset(const allocator_type& a)
+ BOOST_CONTAINER_FORCEINLINE explicit flat_multiset(const allocator_type& a)
: base_t(a)
{}
+ //! @copydoc ::boost::container::flat_set::flat_set(const Compare&, const allocator_type&)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(const Compare& comp, const allocator_type& a)
+ : base_t(comp, a)
+ {}
+
+ //! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator)
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(InputIterator first, InputIterator last)
+ : base_t(false, first, last)
+ {}
+
+ //! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator, const allocator_type&)
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(InputIterator first, InputIterator last, const allocator_type& a)
+ : base_t(false, first, last, a)
+ {}
+
+ //! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator, const Compare& comp)
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(InputIterator first, InputIterator last, const Compare& comp)
+ : base_t(false, first, last, comp)
+ {}
+
//! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator, const Compare& comp, const allocator_type&)
template <class InputIterator>
- flat_multiset(InputIterator first, InputIterator last,
- const Compare& comp = Compare(),
- const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
: base_t(false, first, last, comp, a)
{}
- //! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator, const allocator_type&)
+ //! <b>Effects</b>: Constructs an empty flat_multiset and
+ //! inserts elements from the ordered range [first ,last ). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, InputIterator first, InputIterator last)
+ : base_t(ordered_range, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multiset using the specified comparison object and
+ //! inserts elements from the ordered range [first ,last ). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
template <class InputIterator>
- flat_multiset(InputIterator first, InputIterator last, const allocator_type& a)
- : base_t(false, first, last, Compare(), a)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : base_t(ordered_range, first, last, comp)
{}
//! <b>Effects</b>: Constructs an empty flat_multiset using the specified comparison object and
- //! allocator, and inserts elements from the ordered range [first ,last ). This function
+ //! allocator, and inserts elements from the ordered range [first, last ). This function
//! is more efficient than the normal range creation for ordered ranges.
//!
//! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
@@ -981,22 +1163,55 @@ class flat_multiset
//!
//! <b>Note</b>: Non-standard extension.
template <class InputIterator>
- flat_multiset(ordered_range_t, InputIterator first, InputIterator last,
- const Compare& comp = Compare(),
- const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
: base_t(ordered_range, first, last, comp, a)
{}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list<value_type)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(std::initializer_list<value_type> il)
+ : base_t(false, il.begin(), il.end())
+ {}
+
+ //! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list<value_type>, const allocator_type&)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(std::initializer_list<value_type> il, const allocator_type& a)
+ : base_t(false, il.begin(), il.end(), a)
+ {}
+
+ //! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list<value_type>, const Compare& comp)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(std::initializer_list<value_type> il, const Compare& comp)
+ : base_t(false, il.begin(), il.end(), comp)
+ {}
+
//! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list<value_type>, const Compare& comp, const allocator_type&)
- flat_multiset(std::initializer_list<value_type> il, const Compare& comp = Compare(),
- const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
: base_t(false, il.begin(), il.end(), comp, a)
{}
- //! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list<value_type>, const allocator_type&)
- flat_multiset(std::initializer_list<value_type> il, const allocator_type& a)
- : base_t(false, il.begin(), il.end(), Compare(), a)
+ //! <b>Effects</b>: Constructs an empty containerand
+ //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, std::initializer_list<value_type> il)
+ : base_t(ordered_range, il.begin(), il.end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
+ //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp)
+ : base_t(ordered_range, il.begin(), il.end(), comp)
{}
//! <b>Effects</b>: Constructs an empty container using the specified comparison object and
@@ -1008,39 +1223,38 @@ class flat_multiset
//! <b>Complexity</b>: Linear in N.
//!
//! <b>Note</b>: Non-standard extension.
- flat_multiset(ordered_range_t, std::initializer_list<value_type> il,
- const Compare& comp = Compare(), const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
: base_t(ordered_range, il.begin(), il.end(), comp, a)
{}
#endif
//! @copydoc ::boost::container::flat_set::flat_set(const flat_set &)
- flat_multiset(const flat_multiset& x)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(const flat_multiset& x)
: base_t(static_cast<const base_t&>(x))
{}
//! @copydoc ::boost::container::flat_set::flat_set(flat_set &&)
- flat_multiset(BOOST_RV_REF(flat_multiset) x)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(BOOST_RV_REF(flat_multiset) x)
BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value)
: base_t(boost::move(static_cast<base_t&>(x)))
{}
//! @copydoc ::boost::container::flat_set::flat_set(const flat_set &, const allocator_type &)
- flat_multiset(const flat_multiset& x, const allocator_type &a)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(const flat_multiset& x, const allocator_type &a)
: base_t(static_cast<const base_t&>(x), a)
{}
//! @copydoc ::boost::container::flat_set::flat_set(flat_set &&, const allocator_type &)
- flat_multiset(BOOST_RV_REF(flat_multiset) x, const allocator_type &a)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(BOOST_RV_REF(flat_multiset) x, const allocator_type &a)
: base_t(BOOST_MOVE_BASE(base_t, x), a)
{}
//! @copydoc ::boost::container::flat_set::operator=(const flat_set &)
- flat_multiset& operator=(BOOST_COPY_ASSIGN_REF(flat_multiset) x)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset& operator=(BOOST_COPY_ASSIGN_REF(flat_multiset) x)
{ return static_cast<flat_multiset&>(this->base_t::operator=(static_cast<const base_t&>(x))); }
//! @copydoc ::boost::container::flat_set::operator=(flat_set &&)
- flat_multiset& operator=(BOOST_RV_REF(flat_multiset) x)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset& operator=(BOOST_RV_REF(flat_multiset) x)
BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
allocator_traits_type::is_always_equal::value) &&
boost::container::container_detail::is_nothrow_move_assignable<Compare>::value)
@@ -1140,7 +1354,7 @@ class flat_multiset
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class... Args>
- iterator emplace(BOOST_FWD_REF(Args)... args)
+ BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_FWD_REF(Args)... args)
{ return this->base_t::emplace_equal(boost::forward<Args>(args)...); }
//! <b>Effects</b>: Inserts an object of type Key constructed with
@@ -1155,18 +1369,18 @@ class flat_multiset
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class... Args>
- iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args)
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args)
{ return this->base_t::emplace_hint_equal(p, boost::forward<Args>(args)...); }
#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_CONTAINER_FLAT_MULTISET_EMPLACE_CODE(N) \
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
- iterator emplace(BOOST_MOVE_UREF##N)\
+ BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_MOVE_UREF##N)\
{ return this->base_t::emplace_equal(BOOST_MOVE_FWD##N); }\
\
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
- iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{ return this->base_t::emplace_hint_equal(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
//
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_FLAT_MULTISET_EMPLACE_CODE)
@@ -1233,7 +1447,7 @@ class flat_multiset
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class InputIterator>
- void insert(InputIterator first, InputIterator last)
+ BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
{ this->base_t::insert_equal(first, last); }
//! <b>Requires</b>: first, last are not iterators into *this and
@@ -1247,7 +1461,7 @@ class flat_multiset
//!
//! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
template <class InputIterator>
- void insert(ordered_range_t, InputIterator first, InputIterator last)
+ BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, InputIterator first, InputIterator last)
{ this->base_t::insert_equal(ordered_range, first, last); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@@ -1257,7 +1471,7 @@ class flat_multiset
//! search time plus N*size() insertion time.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- void insert(std::initializer_list<value_type> il)
+ BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
{ this->base_t::insert_equal(il.begin(), il.end()); }
//! <b>Requires</b>: Range [il.begin(), il.end()) must be ordered according to the predicate.
@@ -1269,7 +1483,7 @@ class flat_multiset
//! search time plus N*size() insertion time.
//!
//! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
- void insert(ordered_range_t, std::initializer_list<value_type> il)
+ BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, std::initializer_list<value_type> il)
{ this->base_t::insert_equal(ordered_range, il.begin(), il.end()); }
#endif
@@ -1392,16 +1606,45 @@ class flat_multiset
//! <b>Complexity</b>: Constant.
friend void swap(flat_multiset& x, flat_multiset& y);
+ //! <b>Effects</b>: Extracts the internal sequence container.
+ //!
+ //! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant.
+ //!
+ //! <b>Postcondition</b>: this->empty()
+ //!
+ //! <b>Throws</b>: If secuence_type's move constructor throws
+ sequence_type extract_sequence();
+
#endif //#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+ //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
+ //! one passed externally using the move assignment.
+ //!
+ //! <b>Complexity</b>: Assuming O(1) move assignment, O(NlogN) with N = seq.size()
+ //!
+ //! <b>Throws</b>: If the comparison or the move constructor throws
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence(BOOST_RV_REF(sequence_type) seq)
+ { this->base_t::adopt_sequence_equal(boost::move(seq)); }
+
+ //! <b>Requires</b>: seq shall be ordered according to this->compare()
+ //!
+ //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
+ //! one passed externally using the move assignment.
+ //!
+ //! <b>Complexity</b>: Assuming O(1) move assignment, O(1)
+ //!
+ //! <b>Throws</b>: If the move assignment throws
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_range_t, BOOST_RV_REF(sequence_type) seq)
+ { this->base_t::adopt_sequence_equal(ordered_range_t(), boost::move(seq)); }
+
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
template <class KeyType>
- iterator priv_insert(BOOST_FWD_REF(KeyType) x)
+ BOOST_CONTAINER_FORCEINLINE iterator priv_insert(BOOST_FWD_REF(KeyType) x)
{ return this->base_t::insert_equal(::boost::forward<KeyType>(x)); }
template <class KeyType>
- iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
+ BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
{ return this->base_t::insert_equal(p, ::boost::forward<KeyType>(x)); }
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
diff --git a/boost/container/map.hpp b/boost/container/map.hpp
index 5520fb45ba..33e0331eb0 100644
--- a/boost/container/map.hpp
+++ b/boost/container/map.hpp
@@ -31,6 +31,8 @@
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/value_init.hpp>
#include <boost/container/detail/pair.hpp>
+#include <boost/container/detail/pair_key_mapped_of_value.hpp>
+
// move
#include <boost/move/traits.hpp>
#include <boost/move/utility_core.hpp>
@@ -53,34 +55,6 @@
namespace boost {
namespace container {
-///@cond
-
-template<class Key, class Mapped>
-struct pair_key_mapped_of_value
-{
- typedef Key key_type;
- typedef Mapped mapped_type;
-
- template<class Pair>
- const key_type & key_of_value(const Pair &p) const
- { return p.first; }
-
- template<class Pair>
- const mapped_type & mapped_of_value(const Pair &p) const
- { return p.second; }
-
- template<class Pair>
- key_type & key_of_value(Pair &p) const
- { return const_cast<key_type&>(p.first); }
-
- template<class Pair>
- mapped_type & mapped_of_value(Pair &p) const
- { return p.second; }
-
-};
-
-///@endcond
-
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
//! A map is a kind of associative container that supports unique keys (contains at
@@ -132,7 +106,7 @@ class map
typedef Key key_type;
typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type;
typedef T mapped_type;
- typedef std::pair<const Key, T> value_type;
+ typedef typename boost::container::allocator_traits<Allocator>::value_type value_type;
typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
typedef typename boost::container::allocator_traits<Allocator>::const_pointer const_pointer;
typedef typename boost::container::allocator_traits<Allocator>::reference reference;
@@ -150,14 +124,15 @@ class map
typedef std::pair<key_type, mapped_type> nonconst_value_type;
typedef BOOST_CONTAINER_IMPDEF(movable_value_type_impl) movable_value_type;
typedef BOOST_CONTAINER_IMPDEF(node_handle<
- typename base_t::node_type::container_node_type
- BOOST_MOVE_I value_type
- BOOST_MOVE_I allocator_type
+ typename base_t::stored_allocator_type
BOOST_MOVE_I pair_key_mapped_of_value
<key_type BOOST_MOVE_I mapped_type> >) node_type;
typedef BOOST_CONTAINER_IMPDEF
(insert_return_type_base<iterator BOOST_MOVE_I node_type>) insert_return_type;
+ //allocator_type::value_type type must be std::pair<CONST Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<typename allocator_type::value_type, std::pair<const Key, T> >::value));
+
//////////////////////////////////////////////
//
// construct/copy/destroy
@@ -171,62 +146,99 @@ class map
map() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
container_detail::is_nothrow_default_constructible<Compare>::value)
: base_t()
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ {}
//! <b>Effects</b>: Constructs an empty map using the specified comparison object
//! and allocator.
//!
//! <b>Complexity</b>: Constant.
- BOOST_CONTAINER_FORCEINLINE
- explicit map(const Compare& comp, const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE map(const Compare& comp, const allocator_type& a)
: base_t(comp, a)
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map using the specified comparison object.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE explicit map(const Compare& comp)
+ : base_t(comp)
+ {}
//! <b>Effects</b>: Constructs an empty map using the specified allocator.
//!
//! <b>Complexity</b>: Constant.
- BOOST_CONTAINER_FORCEINLINE
- explicit map(const allocator_type& a)
+ BOOST_CONTAINER_FORCEINLINE explicit map(const allocator_type& a)
: base_t(a)
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ {}
- //! <b>Effects</b>: Constructs an empty map using the specified comparison object and
- //! allocator, and inserts elements from the range [first ,last ).
+ //! <b>Effects</b>: Constructs an empty map and
+ //! inserts elements from the range [first ,last ).
//!
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
- //! comp and otherwise N logN, where N is last - first.
+ //! the predicate and otherwise N logN, where N is last - first.
template <class InputIterator>
- BOOST_CONTAINER_FORCEINLINE
- map(InputIterator first, InputIterator last, const Compare& comp = Compare(),
- const allocator_type& a = allocator_type())
- : base_t(true, first, last, comp, a)
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ BOOST_CONTAINER_FORCEINLINE map(InputIterator first, InputIterator last)
+ : base_t(true, first, last)
+ {}
//! <b>Effects</b>: Constructs an empty map using the specified
//! allocator, and inserts elements from the range [first ,last ).
//!
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
- //! comp and otherwise N logN, where N is last - first.
+ //! the predicate and otherwise N logN, where N is last - first.
template <class InputIterator>
- BOOST_CONTAINER_FORCEINLINE
- map(InputIterator first, InputIterator last, const allocator_type& a)
+ BOOST_CONTAINER_FORCEINLINE map(InputIterator first, InputIterator last, const allocator_type& a)
: base_t(true, first, last, Compare(), a)
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map using the specified comparison object and
+ //! inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE map(InputIterator first, InputIterator last, const Compare& comp)
+ : base_t(true, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map using the specified comparison object and
+ //! allocator, and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE map(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : base_t(true, first, last, comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map and
+ //! inserts elements from the ordered unique range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE map( ordered_unique_range_t, InputIterator first, InputIterator last)
+ : base_t(ordered_range, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map using the specified comparison object and
+ //! inserts elements from the ordered unique range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE map( ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : base_t(ordered_range, first, last, comp)
+ {}
//! <b>Effects</b>: Constructs an empty map using the specified comparison object and
//! allocator, and inserts elements from the ordered unique range [first ,last). This function
@@ -239,43 +251,76 @@ class map
//!
//! <b>Note</b>: Non-standard extension.
template <class InputIterator>
- BOOST_CONTAINER_FORCEINLINE
- map( ordered_unique_range_t, InputIterator first, InputIterator last
- , const Compare& comp = Compare(), const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE map( ordered_unique_range_t, InputIterator first, InputIterator last
+ , const Compare& comp, const allocator_type& a)
: base_t(ordered_range, first, last, comp, a)
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ {}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs an empty map and
+ //! inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted according
+ //! to the predicate and otherwise N logN, where N is il.first() - il.end().
+ BOOST_CONTAINER_FORCEINLINE map(std::initializer_list<value_type> il)
+ : base_t(true, il.begin(), il.end())
+ {}
+
//! <b>Effects</b>: Constructs an empty map using the specified comparison object and
- //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //! inserts elements from the range [il.begin(), il.end()).
//!
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
- //! comp and otherwise N logN, where N is il.first() - il.end().
- BOOST_CONTAINER_FORCEINLINE
- map(std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type())
- : base_t(true, il.begin(), il.end(), comp, a)
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ //! the predicate and otherwise N logN, where N is il.first() - il.end().
+ BOOST_CONTAINER_FORCEINLINE map(std::initializer_list<value_type> il, const Compare& comp)
+ : base_t(true, il.begin(), il.end(), comp)
+ {}
//! <b>Effects</b>: Constructs an empty map using the specified
//! allocator, and inserts elements from the range [il.begin(), il.end()).
//!
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
- //! comp and otherwise N logN, where N is il.first() - il.end().
- BOOST_CONTAINER_FORCEINLINE
- map(std::initializer_list<value_type> il, const allocator_type& a)
+ //! the predicate and otherwise N logN, where N is il.first() - il.end().
+ BOOST_CONTAINER_FORCEINLINE map(std::initializer_list<value_type> il, const allocator_type& a)
: base_t(true, il.begin(), il.end(), Compare(), a)
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ {}
- //! <b>Effects</b>: Constructs an empty set using the specified comparison object and
+ //! <b>Effects</b>: Constructs an empty map using the specified comparison object and
+ //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is il.first() - il.end().
+ BOOST_CONTAINER_FORCEINLINE map(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : base_t(true, il.begin(), il.end(), comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map and inserts elements from the ordered unique range [il.begin(), il.end()).
+ //! This function is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE map(ordered_unique_range_t, std::initializer_list<value_type> il)
+ : base_t(ordered_range, il.begin(), il.end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map using the specified comparison object,
+ //! and inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp)
+ : base_t(ordered_range, il.begin(), il.end(), comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map using the specified comparison object and
//! allocator, and inserts elements from the ordered unique range [il.begin(), il.end()). This function
//! is more efficient than the normal range creation for ordered ranges.
//!
@@ -285,51 +330,36 @@ class map
//! <b>Complexity</b>: Linear in N.
//!
//! <b>Note</b>: Non-standard extension.
- BOOST_CONTAINER_FORCEINLINE
- map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(),
- const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE map( ordered_unique_range_t, std::initializer_list<value_type> il
+ , const Compare& comp, const allocator_type& a)
: base_t(ordered_range, il.begin(), il.end(), comp, a)
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ {}
+
#endif
//! <b>Effects</b>: Copy constructs a map.
//!
//! <b>Complexity</b>: Linear in x.size().
- BOOST_CONTAINER_FORCEINLINE
- map(const map& x)
+ BOOST_CONTAINER_FORCEINLINE map(const map& x)
: base_t(static_cast<const base_t&>(x))
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ {}
//! <b>Effects</b>: Move constructs a map. Constructs *this using x's resources.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Postcondition</b>: x is emptied.
- BOOST_CONTAINER_FORCEINLINE
- map(BOOST_RV_REF(map) x)
+ BOOST_CONTAINER_FORCEINLINE map(BOOST_RV_REF(map) x)
BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value)
: base_t(BOOST_MOVE_BASE(base_t, x))
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ {}
//! <b>Effects</b>: Copy constructs a map using the specified allocator.
//!
//! <b>Complexity</b>: Linear in x.size().
- BOOST_CONTAINER_FORCEINLINE
- map(const map& x, const allocator_type &a)
+ BOOST_CONTAINER_FORCEINLINE map(const map& x, const allocator_type &a)
: base_t(static_cast<const base_t&>(x), a)
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ {}
//! <b>Effects</b>: Move constructs a map using the specified allocator.
//! Constructs *this using x's resources.
@@ -337,19 +367,14 @@ class map
//! <b>Complexity</b>: Constant if x == x.get_allocator(), linear otherwise.
//!
//! <b>Postcondition</b>: x is emptied.
- BOOST_CONTAINER_FORCEINLINE
- map(BOOST_RV_REF(map) x, const allocator_type &a)
+ BOOST_CONTAINER_FORCEINLINE map(BOOST_RV_REF(map) x, const allocator_type &a)
: base_t(BOOST_MOVE_BASE(base_t, x), a)
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ {}
//! <b>Effects</b>: Makes *this a copy of x.
//!
//! <b>Complexity</b>: Linear in x.size().
- BOOST_CONTAINER_FORCEINLINE
- map& operator=(BOOST_COPY_ASSIGN_REF(map) x)
+ BOOST_CONTAINER_FORCEINLINE map& operator=(BOOST_COPY_ASSIGN_REF(map) x)
{ return static_cast<map&>(this->base_t::operator=(static_cast<const base_t&>(x))); }
//! <b>Effects</b>: this->swap(x.get()).
@@ -360,8 +385,7 @@ class map
//! <b>Complexity</b>: Constant if allocator_traits_type::
//! propagate_on_container_move_assignment is true or
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
- BOOST_CONTAINER_FORCEINLINE
- map& operator=(BOOST_RV_REF(map) x)
+ BOOST_CONTAINER_FORCEINLINE map& operator=(BOOST_RV_REF(map) x)
BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
allocator_traits_type::is_always_equal::value) &&
boost::container::container_detail::is_nothrow_move_assignable<Compare>::value)
@@ -370,8 +394,7 @@ class map
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! <b>Effects</b>: Assign content of il to *this.
//!
- BOOST_CONTAINER_FORCEINLINE
- map& operator=(std::initializer_list<value_type> il)
+ BOOST_CONTAINER_FORCEINLINE map& operator=(std::initializer_list<value_type> il)
{
this->clear();
insert(il.begin(), il.end());
@@ -716,7 +739,7 @@ class map
//!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
- iterator insert(const_iterator p, BOOST_RV_REF(nonconst_value_type) x)
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(nonconst_value_type) x)
{ return this->try_emplace(p, boost::move(x.first), boost::move(x.second)); }
//! <b>Effects</b>: Move constructs a new value from x if and only if there is
@@ -728,7 +751,7 @@ class map
//!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
- iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x)
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x)
{ return this->try_emplace(p, boost::move(x.first), boost::move(x.second)); }
//! <b>Effects</b>: Inserts a copy of x in the container.
@@ -746,7 +769,7 @@ class map
//! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
//!
//! <b>Complexity</b>: Logarithmic.
- iterator insert(const_iterator p, BOOST_RV_REF(value_type) x)
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(value_type) x)
{ return this->base_t::insert_unique(p, boost::move(x)); }
//! <b>Requires</b>: first, last are not iterators into *this.
@@ -1225,7 +1248,7 @@ class multimap
typedef Key key_type;
typedef T mapped_type;
- typedef std::pair<const Key, T> value_type;
+ typedef typename boost::container::allocator_traits<Allocator>::value_type value_type;
typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
typedef typename boost::container::allocator_traits<Allocator>::const_pointer const_pointer;
typedef typename boost::container::allocator_traits<Allocator>::reference reference;
@@ -1243,12 +1266,13 @@ class multimap
typedef std::pair<key_type, mapped_type> nonconst_value_type;
typedef BOOST_CONTAINER_IMPDEF(movable_value_type_impl) movable_value_type;
typedef BOOST_CONTAINER_IMPDEF(node_handle<
- typename base_t::node_type::container_node_type
- BOOST_MOVE_I value_type
- BOOST_MOVE_I allocator_type
+ typename base_t::stored_allocator_type
BOOST_MOVE_I pair_key_mapped_of_value
<key_type BOOST_MOVE_I mapped_type> >) node_type;
+ //allocator_type::value_type type must be std::pair<CONST Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<typename allocator_type::value_type, std::pair<const Key, T> >::value));
+
//////////////////////////////////////////////
//
// construct/copy/destroy
@@ -1258,66 +1282,102 @@ class multimap
//! <b>Effects</b>: Default constructs an empty multimap.
//!
//! <b>Complexity</b>: Constant.
- BOOST_CONTAINER_FORCEINLINE
- multimap() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
- container_detail::is_nothrow_default_constructible<Compare>::value)
+ BOOST_CONTAINER_FORCEINLINE multimap()
+ BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
+ container_detail::is_nothrow_default_constructible<Compare>::value)
: base_t()
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ {}
- //! <b>Effects</b>: Constructs an empty multimap using the specified allocator.
+ //! <b>Effects</b>: Constructs an empty multimap using the specified allocator
+ //! object and allocator.
//!
//! <b>Complexity</b>: Constant.
- BOOST_CONTAINER_FORCEINLINE
- explicit multimap(const Compare& comp, const allocator_type& a = allocator_type())
- : base_t(comp, a)
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ BOOST_CONTAINER_FORCEINLINE explicit multimap(const allocator_type& a)
+ : base_t(a)
+ {}
- //! <b>Effects</b>: Constructs an empty multimap using the specified comparison
- //! object and allocator.
+ //! <b>Effects</b>: Constructs an empty multimap using the specified comparison.
//!
//! <b>Complexity</b>: Constant.
- BOOST_CONTAINER_FORCEINLINE
- explicit multimap(const allocator_type& a)
- : base_t(a)
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ BOOST_CONTAINER_FORCEINLINE explicit multimap(const Compare& comp)
+ : base_t(comp)
+ {}
- //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object
- //! and allocator, and inserts elements from the range [first ,last ).
+ //! <b>Effects</b>: Constructs an empty multimap using the specified comparison and allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE multimap(const Compare& comp, const allocator_type& a)
+ : base_t(comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multimap and
+ //! inserts elements from the range [first ,last ).
//!
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
- //! comp and otherwise N logN, where N is last - first.
+ //! the predicate and otherwise N logN, where N is last - first.
template <class InputIterator>
- BOOST_CONTAINER_FORCEINLINE
- multimap(InputIterator first, InputIterator last,
- const Compare& comp = Compare(),
- const allocator_type& a = allocator_type())
- : base_t(false, first, last, comp, a)
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ BOOST_CONTAINER_FORCEINLINE multimap(InputIterator first, InputIterator last)
+ : base_t(false, first, last)
+ {}
//! <b>Effects</b>: Constructs an empty multimap using the specified
//! allocator, and inserts elements from the range [first ,last ).
//!
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
- //! comp and otherwise N logN, where N is last - first.
+ //! the predicate and otherwise N logN, where N is last - first.
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE multimap(InputIterator first, InputIterator last, const allocator_type& a)
: base_t(false, first, last, Compare(), a)
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object and
+ //! inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multimap(InputIterator first, InputIterator last, const Compare& comp)
+ : base_t(false, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object
+ //! and allocator, and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multimap(InputIterator first, InputIterator last,
+ const Compare& comp, const allocator_type& a)
+ : base_t(false, first, last, comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multimap and
+ //! inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, InputIterator first, InputIterator last)
+ : base_t(ordered_range, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object and
+ //! inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : base_t(ordered_range, first, last, comp)
+ {}
//! <b>Effects</b>: Constructs an empty multimap using the specified comparison object and
//! allocator, and inserts elements from the ordered range [first ,last). This function
@@ -1329,41 +1389,51 @@ class multimap
//!
//! <b>Note</b>: Non-standard extension.
template <class InputIterator>
- BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp = Compare(),
- const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp,
+ const allocator_type& a)
: base_t(ordered_range, first, last, comp, a)
{}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
- //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object and
- //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //! <b>Effects</b>: Constructs an empty multimap and
+ //! and inserts elements from the range [il.begin(), il.end()).
//!
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
- //! comp and otherwise N logN, where N is il.first() - il.end().
- BOOST_CONTAINER_FORCEINLINE
- multimap(std::initializer_list<value_type> il, const Compare& comp = Compare(),
- const allocator_type& a = allocator_type())
- : base_t(false, il.begin(), il.end(), comp, a)
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ //! the predicate and otherwise N logN, where N is il.first() - il.end().
+ BOOST_CONTAINER_FORCEINLINE multimap(std::initializer_list<value_type> il)
+ : base_t(false, il.begin(), il.end())
+ {}
//! <b>Effects</b>: Constructs an empty multimap using the specified
//! allocator, and inserts elements from the range [il.begin(), il.end()).
//!
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
- //! comp and otherwise N logN, where N is il.first() - il.end().
- BOOST_CONTAINER_FORCEINLINE
- multimap(std::initializer_list<value_type> il, const allocator_type& a)
+ //! the predicate and otherwise N logN, where N is il.first() - il.end().
+ BOOST_CONTAINER_FORCEINLINE multimap(std::initializer_list<value_type> il, const allocator_type& a)
: base_t(false, il.begin(), il.end(), Compare(), a)
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object and
+ //! inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is il.first() - il.end().
+ BOOST_CONTAINER_FORCEINLINE multimap(std::initializer_list<value_type> il, const Compare& comp)
+ : base_t(false, il.begin(), il.end(), comp)
+ {}
- //! <b>Effects</b>: Constructs an empty set using the specified comparison object and
- //! allocator, and inserts elements from the ordered range [il.begin(), il.end()). This function
+ //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object and
+ //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is il.first() - il.end().
+ BOOST_CONTAINER_FORCEINLINE multimap(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : base_t(false, il.begin(), il.end(), comp, a)
+ {}
+
+
+ //! <b>Effects</b>: Constructs an empty map and
+ //! inserts elements from the ordered range [il.begin(), il.end()). This function
//! is more efficient than the normal range creation for ordered ranges.
//!
//! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
@@ -1371,14 +1441,36 @@ class multimap
//! <b>Complexity</b>: Linear in N.
//!
//! <b>Note</b>: Non-standard extension.
- BOOST_CONTAINER_FORCEINLINE
- multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(),
- const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, std::initializer_list<value_type> il)
+ : base_t(ordered_range, il.begin(), il.end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map using the specified comparison object and
+ //! inserts elements from the ordered range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp)
+ : base_t(ordered_range, il.begin(), il.end(), comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map and
+ //! inserts elements from the ordered range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
: base_t(ordered_range, il.begin(), il.end(), comp, a)
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ {}
+
#endif
//! <b>Effects</b>: Copy constructs a multimap.
@@ -1386,10 +1478,7 @@ class multimap
//! <b>Complexity</b>: Linear in x.size().
BOOST_CONTAINER_FORCEINLINE multimap(const multimap& x)
: base_t(static_cast<const base_t&>(x))
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ {}
//! <b>Effects</b>: Move constructs a multimap. Constructs *this using x's resources.
//!
@@ -1399,20 +1488,14 @@ class multimap
BOOST_CONTAINER_FORCEINLINE multimap(BOOST_RV_REF(multimap) x)
BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value)
: base_t(BOOST_MOVE_BASE(base_t, x))
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ {}
//! <b>Effects</b>: Copy constructs a multimap.
//!
//! <b>Complexity</b>: Linear in x.size().
BOOST_CONTAINER_FORCEINLINE multimap(const multimap& x, const allocator_type &a)
: base_t(static_cast<const base_t&>(x), a)
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ {}
//! <b>Effects</b>: Move constructs a multimap using the specified allocator.
//! Constructs *this using x's resources.
@@ -1421,10 +1504,7 @@ class multimap
//! <b>Postcondition</b>: x is emptied.
BOOST_CONTAINER_FORCEINLINE multimap(BOOST_RV_REF(multimap) x, const allocator_type &a)
: base_t(BOOST_MOVE_BASE(base_t, x), a)
- {
- //A type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
- }
+ {}
//! <b>Effects</b>: Makes *this a copy of x.
//!
@@ -1708,7 +1788,7 @@ class multimap
//!
//! <b>Complexity</b>: N log(a.size() + N) (N has the value source.size())
template<class C2>
- void merge(multimap<Key, T, C2, Allocator, Options>& source)
+ BOOST_CONTAINER_FORCEINLINE void merge(multimap<Key, T, C2, Allocator, Options>& source)
{
typedef container_detail::tree
<value_type_impl, select_1st_t, C2, Allocator, Options> base2_t;
@@ -1717,12 +1797,12 @@ class multimap
//! @copydoc ::boost::container::multimap::merge(multimap<Key, T, C2, Allocator, Options>&)
template<class C2>
- void merge(BOOST_RV_REF_BEG multimap<Key, T, C2, Allocator, Options> BOOST_RV_REF_END source)
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG multimap<Key, T, C2, Allocator, Options> BOOST_RV_REF_END source)
{ return this->merge(static_cast<multimap<Key, T, C2, Allocator, Options>&>(source)); }
//! @copydoc ::boost::container::multimap::merge(multimap<Key, T, C2, Allocator, Options>&)
template<class C2>
- void merge(map<Key, T, C2, Allocator, Options>& source)
+ BOOST_CONTAINER_FORCEINLINE void merge(map<Key, T, C2, Allocator, Options>& source)
{
typedef container_detail::tree
<value_type_impl, select_1st_t, C2, Allocator, Options> base2_t;
@@ -1731,7 +1811,7 @@ class multimap
//! @copydoc ::boost::container::multimap::merge(multimap<Key, T, C2, Allocator, Options>&)
template<class C2>
- void merge(BOOST_RV_REF_BEG map<Key, T, C2, Allocator, Options> BOOST_RV_REF_END source)
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG map<Key, T, C2, Allocator, Options> BOOST_RV_REF_END source)
{ return this->merge(static_cast<map<Key, T, C2, Allocator, Options>&>(source)); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
diff --git a/boost/container/node_handle.hpp b/boost/container/node_handle.hpp
index c46313cc4f..594a09c99e 100644
--- a/boost/container/node_handle.hpp
+++ b/boost/container/node_handle.hpp
@@ -23,7 +23,7 @@
#include <boost/container/detail/workaround.hpp>
#include <boost/static_assert.hpp>
#include <boost/container/detail/placement_new.hpp>
-#include <boost/container/detail/to_raw_pointer.hpp>
+#include <boost/move/detail/to_raw_pointer.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/mpl.hpp>
@@ -40,20 +40,34 @@ namespace container {
///@cond
-template<class Value, class KeyMapped, bool keymapped_is_void = container_detail::is_same<KeyMapped, void>::value>
+template<class Value, class KeyMapped>
struct node_handle_keymapped_traits
{
+ typedef typename KeyMapped::key_type key_type;
+ typedef typename KeyMapped::mapped_type mapped_type;
+};
+
+template<class Value>
+struct node_handle_keymapped_traits<Value, void>
+{
typedef Value key_type;
typedef Value mapped_type;
};
-template<class Value, class KeyMapped>
-struct node_handle_keymapped_traits<Value, KeyMapped, false>
+class node_handle_friend
{
- typedef typename KeyMapped::key_type key_type;
- typedef typename KeyMapped::mapped_type mapped_type;
+ public:
+
+ template<class NH>
+ BOOST_CONTAINER_FORCEINLINE static void destroy_alloc(NH &nh) BOOST_NOEXCEPT
+ { nh.destroy_alloc(); }
+
+ template<class NH>
+ BOOST_CONTAINER_FORCEINLINE static typename NH::node_pointer &get_node_pointer(NH &nh) BOOST_NOEXCEPT
+ { return nh.get_node_pointer(); }
};
+
///@endcond
//! A node_handle is an object that accepts ownership of a single element from an associative container.
@@ -73,76 +87,63 @@ struct node_handle_keymapped_traits<Value, KeyMapped, false>
//!
//! If a node handle is not empty, then it contains an allocator that is equal to the allocator of the container
//! when the element was extracted. If a node handle is empty, it contains no allocator.
-template <class NodeType, class Value, class Allocator, class KeyMapped = void>
+template <class NodeAllocator, class KeyMapped = void>
class node_handle
{
- typedef node_handle_keymapped_traits<Value, KeyMapped> keymapped_t;
+ typedef NodeAllocator nallocator_type;
+ typedef allocator_traits<NodeAllocator> nator_traits;
+ typedef typename nator_traits::value_type priv_node_t;
+ typedef typename priv_node_t::value_type priv_value_t;
+ typedef node_handle_keymapped_traits<priv_value_t, KeyMapped> keymapped_t;
public:
- typedef Value value_type;
+ typedef priv_value_t value_type;
typedef typename keymapped_t::key_type key_type;
typedef typename keymapped_t::mapped_type mapped_type;
- typedef Allocator allocator_type;
- typedef NodeType container_node_type;
+ typedef typename nator_traits::template portable_rebind_alloc
+ <value_type>::type allocator_type;
+
+ typedef priv_node_t container_node_type;
+ friend class node_handle_friend;
///@cond
private:
BOOST_MOVABLE_BUT_NOT_COPYABLE(node_handle)
- typedef allocator_traits<allocator_type> ator_traits;
- typedef typename ator_traits::template portable_rebind_alloc
- <container_node_type>::type nallocator_type;
- typedef allocator_traits<nallocator_type> node_ator_traits;
- typedef typename node_ator_traits::pointer node_pointer;
+ typedef typename nator_traits::pointer node_pointer;
typedef ::boost::aligned_storage
- <sizeof(allocator_type), boost::alignment_of<nallocator_type>::value> nalloc_storage_t;
+ < sizeof(nallocator_type)
+ , boost::alignment_of<nallocator_type>::value> nalloc_storage_t;
node_pointer m_ptr;
nalloc_storage_t m_nalloc_storage;
void move_construct_alloc(nallocator_type &al)
- { ::new(m_nalloc_storage.address(), boost_container_new_t()) allocator_type(::boost::move(al)); }
+ { ::new(m_nalloc_storage.address(), boost_container_new_t()) nallocator_type(::boost::move(al)); }
- void destroy_node()
+ void destroy_deallocate_node()
{
- node_ator_traits::destroy(this->node_alloc(), container_detail::to_raw_pointer(m_ptr));
- node_ator_traits::deallocate(this->node_alloc(), m_ptr, 1u);
+ nator_traits::destroy(this->node_alloc(), boost::movelib::to_raw_pointer(m_ptr));
+ nator_traits::deallocate(this->node_alloc(), m_ptr, 1u);
}
template<class OtherNodeHandle>
void move_construct_end(OtherNodeHandle &nh)
{
if(m_ptr){
- ::new (m_nalloc_storage.address(), boost_container_new_t()) allocator_type(::boost::move(nh.node_alloc()));
- nh.destroy_alloc();
- nh.get_node_pointer() = node_pointer();
+ ::new (m_nalloc_storage.address(), boost_container_new_t()) nallocator_type(::boost::move(nh.node_alloc()));
+ node_handle_friend::destroy_alloc(nh);
+ node_handle_friend::get_node_pointer(nh) = node_pointer();
}
BOOST_ASSERT(nh.empty());
}
- public:
-
- void destroy_alloc()
- { static_cast<allocator_type*>(m_nalloc_storage.address())->~allocator_type(); }
+ void destroy_alloc() BOOST_NOEXCEPT
+ { static_cast<nallocator_type*>(m_nalloc_storage.address())->~nallocator_type(); }
- node_pointer &get_node_pointer()
+ node_pointer &get_node_pointer() BOOST_NOEXCEPT
{ return m_ptr; }
- nallocator_type &node_alloc()
- { return *static_cast<nallocator_type*>(m_nalloc_storage.address()); }
-
- const nallocator_type &node_alloc() const
- { return *static_cast<const nallocator_type*>(m_nalloc_storage.address()); }
-
- node_pointer release()
- {
- node_pointer p(m_ptr);
- m_ptr = node_pointer();
- if(p)
- this->destroy_alloc();
- return p;
- }
-
///@endcond
public:
@@ -150,13 +151,13 @@ class node_handle
//!
//! <b>Postcondition</b>: this->empty()
BOOST_CXX14_CONSTEXPR node_handle() BOOST_NOEXCEPT
- : m_ptr(), m_nalloc_storage()
- { BOOST_ASSERT(this->empty()); }
+ : m_ptr()
+ { }
//! <b>Effects</b>: Constructs a node_handle object initializing internal pointer with p.
- //! If p != nullptr copy constructs internal allocator al.
+ //! If p != nullptr copy constructs internal allocator from al.
node_handle(node_pointer p, const nallocator_type &al) BOOST_NOEXCEPT
- : m_ptr(p), m_nalloc_storage()
+ : m_ptr(p)
{
if(m_ptr){
::new (m_nalloc_storage.address(), boost_container_new_t()) nallocator_type(al);
@@ -172,12 +173,12 @@ class node_handle
//! <b>Note</b>: Two node_handle's are related if only one of KeyMapped template parameter
//! of a node handle is void.
template<class KeyMapped2>
- node_handle( BOOST_RV_REF_BEG node_handle<NodeType, Value, Allocator, KeyMapped2> BOOST_RV_REF_END nh
+ node_handle( BOOST_RV_REF_BEG node_handle<NodeAllocator, KeyMapped2> BOOST_RV_REF_END nh
, typename container_detail::enable_if_c
< ((unsigned)container_detail::is_same<KeyMapped, void>::value +
(unsigned)container_detail::is_same<KeyMapped2, void>::value) == 1u
- >::type* = 0)
- : m_ptr(nh.get_node_pointer()), m_nalloc_storage()
+ >::type* = 0) BOOST_NOEXCEPT
+ : m_ptr(nh.get())
{ this->move_construct_end(nh); }
//! <b>Effects</b>: Constructs a node_handle object initializing internal pointer with nh's internal pointer
@@ -186,43 +187,44 @@ class node_handle
//!
//! <b>Postcondition</b>: nh.empty()
node_handle (BOOST_RV_REF(node_handle) nh) BOOST_NOEXCEPT
- : m_ptr(nh.m_ptr), m_nalloc_storage()
+ : m_ptr(nh.m_ptr)
{ this->move_construct_end(nh); }
//! <b>Effects</b>: If !this->empty(), destroys the value_type subobject in the container_node_type object
//! pointed to by c by calling allocator_traits<impl_defined>::destroy, then deallocates m_ptr by calling
- //! ator_traits::rebind_traits<container_node_type>::deallocate.
- ~node_handle () BOOST_NOEXCEPT
+ //! nator_traits::rebind_traits<container_node_type>::deallocate.
+ ~node_handle() BOOST_NOEXCEPT
{
if(!this->empty()){
- this->destroy_node();
+ this->destroy_deallocate_node();
this->destroy_alloc();
}
}
- //! <b>Requires</b>: Either this->empty(), or ator_traits::propagate_on_container_move_assignment is true, or
+ //! <b>Requires</b>: Either this->empty(), or nator_traits::propagate_on_container_move_assignment is true, or
//! node_alloc() == nh.node_alloc().
//!
//! <b>Effects</b>: If m_ptr != nullptr, destroys the value_type subobject in the container_node_type object
- //! pointed to by m_ptr by calling ator_traits::destroy, then deallocates m_ptr by calling ator_-
- //! traits::rebind_traits<container_node_type>::deallocate. Assigns nh.m_ptr to m_ptr. If this->empty()
- //! or ator_traits::propagate_on_container_move_assignment is true, move assigns nh.node_alloc() to
+ //! pointed to by m_ptr by calling nator_traits::destroy, then deallocates m_ptr by calling
+ //! nator_traits::deallocate. Assigns nh.m_ptr to m_ptr. If this->empty()
+ //! or nator_traits::propagate_on_container_move_assignment is true, move assigns nh.node_alloc() to
//! node_alloc(). Assigns nullptr to nh.m_ptr and assigns nullopt to nh.node_alloc().
+ //!
//! <b>Returns</b>: *this.
//!
//! <b>Throws</b>: Nothing.
- node_handle & operator=(BOOST_RV_REF(node_handle) nh)
+ node_handle & operator=(BOOST_RV_REF(node_handle) nh) BOOST_NOEXCEPT
{
- BOOST_ASSERT(this->empty() || nh.empty() || ator_traits::propagate_on_container_move_assignment::value
- || ator_traits::equal(node_alloc(), nh.node_alloc()));
+ BOOST_ASSERT(this->empty() || nator_traits::propagate_on_container_move_assignment::value
+ || nator_traits::equal(node_alloc(), nh.node_alloc()));
bool const was_this_non_null = !this->empty();
bool const was_nh_non_null = !nh.empty();
if(was_nh_non_null){
if(was_this_non_null){
- this->destroy_node();
- if(ator_traits::propagate_on_container_move_assignment::value){
+ this->destroy_deallocate_node();
+ if(nator_traits::propagate_on_container_move_assignment::value){
this->node_alloc() = ::boost::move(nh.node_alloc());
}
}
@@ -234,7 +236,7 @@ class node_handle
nh.destroy_alloc();
}
else if(was_this_non_null){
- this->destroy_node();
+ this->destroy_deallocate_node();
this->destroy_alloc();
m_ptr = node_pointer();
}
@@ -310,23 +312,23 @@ class node_handle
return !this->m_ptr;
}
- //! <b>Requires</b>: this->empty(), or nh.empty(), or ator_traits::propagate_on_container_swap is true, or
+ //! <b>Requires</b>: this->empty(), or nh.empty(), or nator_traits::propagate_on_container_swap is true, or
//! node_alloc() == nh.node_alloc().
//!
- //! <b>Effects</b>: Calls swap(m_ptr, nh.m_ptr). If this->empty(), or nh.empty(), or ator_traits::propagate_on_-
+ //! <b>Effects</b>: Calls swap(m_ptr, nh.m_ptr). If this->empty(), or nh.empty(), or nator_traits::propagate_on_-
//! container_swap is true calls swap(node_alloc(), nh.node_alloc()).
void swap(node_handle &nh)
- BOOST_NOEXCEPT_IF(ator_traits::propagate_on_container_swap::value || ator_traits::is_always_equal::value)
+ BOOST_NOEXCEPT_IF(nator_traits::propagate_on_container_swap::value || nator_traits::is_always_equal::value)
{
- BOOST_ASSERT(this->empty() || nh.empty() || ator_traits::propagate_on_container_swap::value
- || ator_traits::equal(node_alloc(), nh.node_alloc()));
+ BOOST_ASSERT(this->empty() || nh.empty() || nator_traits::propagate_on_container_swap::value
+ || nator_traits::equal(node_alloc(), nh.node_alloc()));
bool const was_this_non_null = !this->empty();
bool const was_nh_non_null = !nh.empty();
if(was_nh_non_null){
if(was_this_non_null){
- if(ator_traits::propagate_on_container_swap::value){
+ if(nator_traits::propagate_on_container_swap::value){
::boost::adl_move_swap(this->node_alloc(), nh.node_alloc());
}
}
@@ -337,11 +339,53 @@ class node_handle
}
else if(was_this_non_null){
nh.move_construct_alloc(this->node_alloc());
- nh.destroy_alloc();
+ this->destroy_alloc();
}
::boost::adl_move_swap(m_ptr, nh.m_ptr);
}
+ //! <b>Effects</b>: If this->empty() returns nullptr, otherwise returns m_ptr
+ //! resets m_ptr to nullptr and destroys the internal allocator.
+ //!
+ //! <b>Postcondition</b>: this->empty()
+ //!
+ //! <b>Note</b>: Non-standard extensions
+ node_pointer release() BOOST_NOEXCEPT
+ {
+ node_pointer p(m_ptr);
+ m_ptr = node_pointer();
+ if(p)
+ this->destroy_alloc();
+ return p;
+ }
+
+ //! <b>Effects</b>: Returns m_ptr.
+ //!
+ //! <b>Note</b>: Non-standard extensions
+ node_pointer get() const BOOST_NOEXCEPT
+ {
+ return m_ptr;
+ }
+
+ //! <b>Effects</b>: Returns a reference to the internal node allocator.
+ //!
+ //! <b>Note</b>: Non-standard extensions
+ nallocator_type &node_alloc() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT(!empty());
+ return *static_cast<nallocator_type*>(m_nalloc_storage.address());
+ }
+
+
+ //! <b>Effects</b>: Returns a reference to the internal node allocator.
+ //!
+ //! <b>Note</b>: Non-standard extensions
+ const nallocator_type &node_alloc() const BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT(!empty());
+ return *static_cast<const nallocator_type*>(m_nalloc_storage.address());
+ }
+
//! <b>Effects</b>: x.swap(y).
//!
friend void swap(node_handle & x, node_handle & y) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
diff --git a/boost/container/set.hpp b/boost/container/set.hpp
index 5cf0f964a5..8730b1c89a 100644
--- a/boost/container/set.hpp
+++ b/boost/container/set.hpp
@@ -112,46 +112,103 @@ class set
//! <b>Effects</b>: Default constructs an empty set.
//!
//! <b>Complexity</b>: Constant.
- set() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
- container_detail::is_nothrow_default_constructible<Compare>::value)
+
+ BOOST_CONTAINER_FORCEINLINE set()
+ BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
+ container_detail::is_nothrow_default_constructible<Compare>::value)
: base_t()
{}
+ //! <b>Effects</b>: Constructs an empty set using the specified allocator object.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE explicit set(const allocator_type& a)
+ : base_t(a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set using the specified comparison object.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE explicit set(const Compare& comp)
+ : base_t(comp)
+ {}
+
//! <b>Effects</b>: Constructs an empty set using the specified comparison object
//! and allocator.
//!
//! <b>Complexity</b>: Constant.
- explicit set(const Compare& comp,
- const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE set(const Compare& comp, const allocator_type& a)
: base_t(comp, a)
{}
- //! <b>Effects</b>: Constructs an empty set using the specified allocator object.
+ //! <b>Effects</b>: Constructs an empty set using and
+ //! inserts elements from the range [first ,last ).
//!
- //! <b>Complexity</b>: Constant.
- explicit set(const allocator_type& a)
- : base_t(a)
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE set(InputIterator first, InputIterator last)
+ : base_t(true, first, last)
{}
- //! <b>Effects</b>: Constructs an empty set using the specified comparison object and
+ //! <b>Effects</b>: Constructs an empty set using the specified
//! allocator, and inserts elements from the range [first ,last ).
//!
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
- //! comp and otherwise N logN, where N is last - first.
+ //! the predicate and otherwise N logN, where N is last - first.
template <class InputIterator>
- set(InputIterator first, InputIterator last, const Compare& comp = Compare(),
- const allocator_type& a = allocator_type())
- : base_t(true, first, last, comp, a)
+ BOOST_CONTAINER_FORCEINLINE set(InputIterator first, InputIterator last, const allocator_type& a)
+ : base_t(true, first, last, key_compare(), a)
{}
- //! <b>Effects</b>: Constructs an empty set using the specified
+ //! <b>Effects</b>: Constructs an empty set using the specified comparison object and
+ //! inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE set(InputIterator first, InputIterator last, const Compare& comp)
+ : base_t(true, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set using the specified comparison object and
//! allocator, and inserts elements from the range [first ,last ).
//!
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
- //! comp and otherwise N logN, where N is last - first.
+ //! the predicate and otherwise N logN, where N is last - first.
template <class InputIterator>
- set(InputIterator first, InputIterator last, const allocator_type& a)
- : base_t(true, first, last, key_compare(), a)
+ BOOST_CONTAINER_FORCEINLINE set(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : base_t(true, first, last, comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set and
+ //! inserts elements from the ordered unique range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE set( ordered_unique_range_t, InputIterator first, InputIterator last)
+ : base_t(ordered_range, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set using the specified comparison object and
+ //! inserts elements from the ordered unique range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE set( ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp )
+ : base_t(ordered_range, first, last, comp)
{}
//! <b>Effects</b>: Constructs an empty set using the specified comparison object and
@@ -165,31 +222,77 @@ class set
//!
//! <b>Note</b>: Non-standard extension.
template <class InputIterator>
- set( ordered_unique_range_t, InputIterator first, InputIterator last
- , const Compare& comp = Compare(), const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE set( ordered_unique_range_t, InputIterator first, InputIterator last
+ , const Compare& comp, const allocator_type& a)
: base_t(ordered_range, first, last, comp, a)
{}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
- //! <b>Effects</b>: Constructs an empty set using the specified comparison object and
- //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //! <b>Effects</b>: Constructs an empty set and
+ //! inserts elements from the range [il.begin(), il.end()).
//!
//! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
- //! comp and otherwise N logN, where N is il.begin() - il.end().
- set(std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type())
- : base_t(true, il.begin(), il.end(), comp, a)
+ //! the predicate and otherwise N logN, where N is il.begin() - il.end().
+ BOOST_CONTAINER_FORCEINLINE set(std::initializer_list<value_type> il)
+ : base_t(true, il.begin(), il.end())
{}
//! <b>Effects</b>: Constructs an empty set using the specified
//! allocator, and inserts elements from the range [il.begin(), il.end()).
//!
//! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
- //! comp and otherwise N logN, where N is il.begin() - il.end().
- set(std::initializer_list<value_type> il, const allocator_type& a)
+ //! the predicate and otherwise N logN, where N is il.begin() - il.end().
+ BOOST_CONTAINER_FORCEINLINE set(std::initializer_list<value_type> il, const allocator_type& a)
: base_t(true, il.begin(), il.end(), Compare(), a)
{}
//! <b>Effects</b>: Constructs an empty set using the specified comparison object and
+ //! inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is il.begin() - il.end().
+ BOOST_CONTAINER_FORCEINLINE set(std::initializer_list<value_type> il, const Compare& comp )
+ : base_t(true, il.begin(), il.end(), comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set using the specified comparison object and
+ //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is il.begin() - il.end().
+ BOOST_CONTAINER_FORCEINLINE set(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : base_t(true, il.begin(), il.end(), comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set and
+ //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE set( ordered_unique_range_t, std::initializer_list<value_type> il)
+ : base_t(ordered_range, il.begin(), il.end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set using the specified comparison object and
+ //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE set( ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp)
+ : base_t(ordered_range, il.begin(), il.end(), comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set using the specified comparison object and
//! allocator, and inserts elements from the ordered unique range [il.begin(), il.end()). This function
//! is more efficient than the normal range creation for ordered ranges.
//!
@@ -199,8 +302,7 @@ class set
//! <b>Complexity</b>: Linear in N.
//!
//! <b>Note</b>: Non-standard extension.
- set( ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare()
- , const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE set( ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
: base_t(ordered_range, il.begin(), il.end(), comp, a)
{}
#endif
@@ -208,7 +310,7 @@ class set
//! <b>Effects</b>: Copy constructs a set.
//!
//! <b>Complexity</b>: Linear in x.size().
- set(const set& x)
+ BOOST_CONTAINER_FORCEINLINE set(const set& x)
: base_t(static_cast<const base_t&>(x))
{}
@@ -217,7 +319,7 @@ class set
//! <b>Complexity</b>: Constant.
//!
//! <b>Postcondition</b>: x is emptied.
- set(BOOST_RV_REF(set) x)
+ BOOST_CONTAINER_FORCEINLINE set(BOOST_RV_REF(set) x)
BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value)
: base_t(BOOST_MOVE_BASE(base_t, x))
{}
@@ -225,7 +327,7 @@ class set
//! <b>Effects</b>: Copy constructs a set using the specified allocator.
//!
//! <b>Complexity</b>: Linear in x.size().
- set(const set& x, const allocator_type &a)
+ BOOST_CONTAINER_FORCEINLINE set(const set& x, const allocator_type &a)
: base_t(static_cast<const base_t&>(x), a)
{}
@@ -233,14 +335,14 @@ class set
//! Constructs *this using x's resources.
//!
//! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
- set(BOOST_RV_REF(set) x, const allocator_type &a)
+ BOOST_CONTAINER_FORCEINLINE set(BOOST_RV_REF(set) x, const allocator_type &a)
: base_t(BOOST_MOVE_BASE(base_t, x), a)
{}
//! <b>Effects</b>: Makes *this a copy of x.
//!
//! <b>Complexity</b>: Linear in x.size().
- set& operator=(BOOST_COPY_ASSIGN_REF(set) x)
+ BOOST_CONTAINER_FORCEINLINE set& operator=(BOOST_COPY_ASSIGN_REF(set) x)
{ return static_cast<set&>(this->base_t::operator=(static_cast<const base_t&>(x))); }
//! <b>Effects</b>: this->swap(x.get()).
@@ -251,7 +353,7 @@ class set
//! <b>Complexity</b>: Constant if allocator_traits_type::
//! propagate_on_container_move_assignment is true or
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
- set& operator=(BOOST_RV_REF(set) x)
+ BOOST_CONTAINER_FORCEINLINE set& operator=(BOOST_RV_REF(set) x)
BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
allocator_traits_type::is_always_equal::value) &&
boost::container::container_detail::is_nothrow_move_assignable<Compare>::value)
@@ -424,7 +526,7 @@ class set
//!
//! <b>Complexity</b>: Logarithmic.
template <class... Args>
- std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args)
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args)
{ return this->base_t::emplace_unique(boost::forward<Args>(args)...); }
//! <b>Effects</b>: Inserts an object of type Key constructed with
@@ -437,18 +539,18 @@ class set
//!
//! <b>Complexity</b>: Logarithmic.
template <class... Args>
- iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args)
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args)
{ return this->base_t::emplace_hint_unique(p, boost::forward<Args>(args)...); }
#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_CONTAINER_SET_EMPLACE_CODE(N) \
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
- std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\
{ return this->base_t::emplace_unique(BOOST_MOVE_FWD##N); }\
\
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
- iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{ return this->base_t::emplace_hint_unique(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
//
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SET_EMPLACE_CODE)
@@ -513,7 +615,7 @@ class set
//!
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
template <class InputIterator>
- void insert(InputIterator first, InputIterator last)
+ BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
{ this->base_t::insert_unique(first, last); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@@ -521,16 +623,16 @@ class set
//! if there is no element with key equivalent to the key of that element.
//!
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.begin() to il.end())
- void insert(std::initializer_list<value_type> il)
+ BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
{ this->base_t::insert_unique(il.begin(), il.end()); }
#endif
//! @copydoc ::boost::container::map::insert(node_type&&)
- insert_return_type insert(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
+ BOOST_CONTAINER_FORCEINLINE insert_return_type insert(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
{ return this->base_t::insert_unique_node(boost::move(nh)); }
//! @copydoc ::boost::container::map::insert(const_iterator, node_type&&)
- insert_return_type insert(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
+ BOOST_CONTAINER_FORCEINLINE insert_return_type insert(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
{ return this->base_t::insert_unique_node(hint, boost::move(nh)); }
//! @copydoc ::boost::container::map::merge(map<Key, T, C2, Allocator, Options>&)
@@ -586,6 +688,12 @@ class set
//! <b>Complexity</b>: log(size())+N where N is the distance from first to last.
iterator erase(const_iterator first, const_iterator last);
+ //! @copydoc ::boost::container::map::extract(const_iterator)
+ node_type extract(const_iterator p);
+
+ //! @copydoc ::boost::container::map::extract(const key_type&)
+ node_type extract(const key_type& x);
+
//! <b>Effects</b>: Swaps the contents of *this and x.
//!
//! <b>Throws</b>: Nothing.
@@ -631,13 +739,13 @@ class set
//! <b>Returns</b>: The number of elements with key equivalent to x.
//!
//! <b>Complexity</b>: log(size())+count(k)
- size_type count(const key_type& x) const
+ BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const
{ return static_cast<size_type>(this->base_t::find(x) != this->base_t::cend()); }
//! <b>Returns</b>: The number of elements with key equivalent to x.
//!
//! <b>Complexity</b>: log(size())+count(k)
- size_type count(const key_type& x)
+ BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x)
{ return static_cast<size_type>(this->base_t::find(x) != this->base_t::end()); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -671,13 +779,13 @@ class set
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
- std::pair<iterator,iterator> equal_range(const key_type& x)
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const key_type& x)
{ return this->base_t::lower_bound_range(x); }
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
- std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
+ BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
{ return this->base_t::lower_bound_range(x); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -737,11 +845,11 @@ class set
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
template <class KeyType>
- std::pair<iterator, bool> priv_insert(BOOST_FWD_REF(KeyType) x)
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> priv_insert(BOOST_FWD_REF(KeyType) x)
{ return this->base_t::insert_unique(::boost::forward<KeyType>(x)); }
template <class KeyType>
- iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
+ BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
{ return this->base_t::insert_unique(p, ::boost::forward<KeyType>(x)); }
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
@@ -829,34 +937,77 @@ class multiset
//////////////////////////////////////////////
//! @copydoc ::boost::container::set::set()
- multiset() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
- container_detail::is_nothrow_default_constructible<Compare>::value)
+ BOOST_CONTAINER_FORCEINLINE multiset()
+ BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
+ container_detail::is_nothrow_default_constructible<Compare>::value)
: base_t()
{}
+ //! @copydoc ::boost::container::set::set(const allocator_type&)
+ BOOST_CONTAINER_FORCEINLINE explicit multiset(const allocator_type& a)
+ : base_t(a)
+ {}
+
+ //! @copydoc ::boost::container::set::set(const Compare&)
+ BOOST_CONTAINER_FORCEINLINE explicit multiset(const Compare& comp)
+ : base_t(comp)
+ {}
+
//! @copydoc ::boost::container::set::set(const Compare&, const allocator_type&)
- explicit multiset(const Compare& comp,
- const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE multiset(const Compare& comp, const allocator_type& a)
: base_t(comp, a)
{}
- //! @copydoc ::boost::container::set::set(const allocator_type&)
- explicit multiset(const allocator_type& a)
- : base_t(a)
+ //! @copydoc ::boost::container::set::set(InputIterator, InputIterator)
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multiset(InputIterator first, InputIterator last)
+ : base_t(false, first, last)
+ {}
+
+ //! @copydoc ::boost::container::set::set(InputIterator, InputIterator, const allocator_type&)
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multiset(InputIterator first, InputIterator last, const allocator_type& a)
+ : base_t(false, first, last, key_compare(), a)
{}
- //! @copydoc ::boost::container::set::set(InputIterator, InputIterator, const Compare& comp, const allocator_type&)
+ //! @copydoc ::boost::container::set::set(InputIterator, InputIterator, const Compare&)
template <class InputIterator>
- multiset(InputIterator first, InputIterator last,
- const Compare& comp = Compare(),
- const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE multiset(InputIterator first, InputIterator last, const Compare& comp)
+ : base_t(false, first, last, comp)
+ {}
+
+ //! @copydoc ::boost::container::set::set(InputIterator, InputIterator, const Compare&, const allocator_type&)
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multiset(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
: base_t(false, first, last, comp, a)
{}
- //! @copydoc ::boost::container::set::set(InputIterator, InputIterator, const allocator_type&)
+ //! <b>Effects</b>: Constructs an empty multiset and
+ //! and inserts elements from the ordered range [first ,last ). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
template <class InputIterator>
- multiset(InputIterator first, InputIterator last, const allocator_type& a)
- : base_t(false, first, last, key_compare(), a)
+ BOOST_CONTAINER_FORCEINLINE multiset( ordered_range_t, InputIterator first, InputIterator last )
+ : base_t(ordered_range, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multiset using the specified comparison object and
+ //! inserts elements from the ordered range [first ,last ). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multiset( ordered_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : base_t(ordered_range, first, last, comp)
{}
//! <b>Effects</b>: Constructs an empty multiset using the specified comparison object and
@@ -869,56 +1020,74 @@ class multiset
//!
//! <b>Note</b>: Non-standard extension.
template <class InputIterator>
- multiset( ordered_range_t, InputIterator first, InputIterator last
- , const Compare& comp = Compare()
- , const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE multiset( ordered_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
: base_t(ordered_range, first, last, comp, a)
{}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
- //! @copydoc ::boost::container::set::set(std::initializer_list<value_type>, const Compare& comp, const allocator_type&)
- multiset(std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type())
- : base_t(false, il.begin(), il.end(), comp, a)
+ //! @copydoc ::boost::container::set::set(std::initializer_list<value_type>)
+ BOOST_CONTAINER_FORCEINLINE multiset(std::initializer_list<value_type> il)
+ : base_t(false, il.begin(), il.end())
{}
//! @copydoc ::boost::container::set::set(std::initializer_list<value_type>, const allocator_type&)
- multiset(std::initializer_list<value_type> il, const allocator_type& a)
+ BOOST_CONTAINER_FORCEINLINE multiset(std::initializer_list<value_type> il, const allocator_type& a)
: base_t(false, il.begin(), il.end(), Compare(), a)
{}
- //! @copydoc ::boost::container::set::set(ordered_unique_range_t, std::initializer_list<value_type>, const Compare& comp, const allocator_type&)
- multiset(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type())
+ //! @copydoc ::boost::container::set::set(std::initializer_list<value_type>, const Compare&)
+ BOOST_CONTAINER_FORCEINLINE multiset(std::initializer_list<value_type> il, const Compare& comp)
+ : base_t(false, il.begin(), il.end(), comp)
+ {}
+
+ //! @copydoc ::boost::container::set::set(std::initializer_list<value_type>, const Compare&, const allocator_type&)
+ BOOST_CONTAINER_FORCEINLINE multiset(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : base_t(false, il.begin(), il.end(), comp, a)
+ {}
+
+ //! @copydoc ::boost::container::set::set(ordered_unique_range_t, std::initializer_list<value_type>)
+ BOOST_CONTAINER_FORCEINLINE multiset(ordered_range_t, std::initializer_list<value_type> il)
+ : base_t(ordered_range, il.begin(), il.end())
+ {}
+
+ //! @copydoc ::boost::container::set::set(ordered_unique_range_t, std::initializer_list<value_type>, const Compare&)
+ BOOST_CONTAINER_FORCEINLINE multiset(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp)
+ : base_t(ordered_range, il.begin(), il.end(), comp)
+ {}
+
+ //! @copydoc ::boost::container::set::set(ordered_unique_range_t, std::initializer_list<value_type>, const Compare&, const allocator_type&)
+ BOOST_CONTAINER_FORCEINLINE multiset(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
: base_t(ordered_range, il.begin(), il.end(), comp, a)
{}
#endif
//! @copydoc ::boost::container::set::set(const set &)
- multiset(const multiset& x)
+ BOOST_CONTAINER_FORCEINLINE multiset(const multiset& x)
: base_t(static_cast<const base_t&>(x))
{}
//! @copydoc ::boost::container::set::set(set &&)
- multiset(BOOST_RV_REF(multiset) x)
+ BOOST_CONTAINER_FORCEINLINE multiset(BOOST_RV_REF(multiset) x)
BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value)
: base_t(BOOST_MOVE_BASE(base_t, x))
{}
//! @copydoc ::boost::container::set::set(const set &, const allocator_type &)
- multiset(const multiset& x, const allocator_type &a)
+ BOOST_CONTAINER_FORCEINLINE multiset(const multiset& x, const allocator_type &a)
: base_t(static_cast<const base_t&>(x), a)
{}
//! @copydoc ::boost::container::set::set(set &&, const allocator_type &)
- multiset(BOOST_RV_REF(multiset) x, const allocator_type &a)
+ BOOST_CONTAINER_FORCEINLINE multiset(BOOST_RV_REF(multiset) x, const allocator_type &a)
: base_t(BOOST_MOVE_BASE(base_t, x), a)
{}
//! @copydoc ::boost::container::set::operator=(const set &)
- multiset& operator=(BOOST_COPY_ASSIGN_REF(multiset) x)
+ BOOST_CONTAINER_FORCEINLINE multiset& operator=(BOOST_COPY_ASSIGN_REF(multiset) x)
{ return static_cast<multiset&>(this->base_t::operator=(static_cast<const base_t&>(x))); }
//! @copydoc ::boost::container::set::operator=(set &&)
- multiset& operator=(BOOST_RV_REF(multiset) x)
+ BOOST_CONTAINER_FORCEINLINE multiset& operator=(BOOST_RV_REF(multiset) x)
BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
allocator_traits_type::is_always_equal::value) &&
boost::container::container_detail::is_nothrow_move_assignable<Compare>::value)
@@ -999,7 +1168,7 @@ class multiset
//!
//! <b>Complexity</b>: Logarithmic.
template <class... Args>
- iterator emplace(BOOST_FWD_REF(Args)... args)
+ BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_FWD_REF(Args)... args)
{ return this->base_t::emplace_equal(boost::forward<Args>(args)...); }
//! <b>Effects</b>: Inserts an object of type Key constructed with
@@ -1011,18 +1180,18 @@ class multiset
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
template <class... Args>
- iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args)
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args)
{ return this->base_t::emplace_hint_equal(p, boost::forward<Args>(args)...); }
#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_CONTAINER_MULTISET_EMPLACE_CODE(N) \
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
- iterator emplace(BOOST_MOVE_UREF##N)\
+ BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_MOVE_UREF##N)\
{ return this->base_t::emplace_equal(BOOST_MOVE_FWD##N); }\
\
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
- iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{ return this->base_t::emplace_hint_equal(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
//
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_MULTISET_EMPLACE_CODE)
@@ -1079,21 +1248,21 @@ class multiset
//!
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
template <class InputIterator>
- void insert(InputIterator first, InputIterator last)
+ BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
{ this->base_t::insert_equal(first, last); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! @copydoc ::boost::container::set::insert(std::initializer_list<value_type>)
- void insert(std::initializer_list<value_type> il)
+ BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
{ this->base_t::insert_equal(il.begin(), il.end()); }
#endif
//! @copydoc ::boost::container::multimap::insert(node_type&&)
- iterator insert(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
+ BOOST_CONTAINER_FORCEINLINE iterator insert(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
{ return this->base_t::insert_equal_node(boost::move(nh)); }
//! @copydoc ::boost::container::multimap::insert(const_iterator, node_type&&)
- iterator insert(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
{ return this->base_t::insert_equal_node(hint, boost::move(nh)); }
//! @copydoc ::boost::container::multimap::merge(multimap<Key, T, C2, Allocator, Options>&)
@@ -1135,6 +1304,12 @@ class multiset
//! @copydoc ::boost::container::set::erase(const_iterator,const_iterator)
iterator erase(const_iterator first, const_iterator last);
+ //! @copydoc ::boost::container::multimap::extract(const_iterator)
+ node_type extract(const_iterator p);
+
+ //! @copydoc ::boost::container::multimap::extract(const key_type&)
+ node_type extract(const key_type& x);
+
//! @copydoc ::boost::container::set::swap
void swap(multiset& x)
BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
@@ -1219,11 +1394,11 @@ class multiset
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
template <class KeyType>
- iterator priv_insert(BOOST_FWD_REF(KeyType) x)
+ BOOST_CONTAINER_FORCEINLINE iterator priv_insert(BOOST_FWD_REF(KeyType) x)
{ return this->base_t::insert_equal(::boost::forward<KeyType>(x)); }
template <class KeyType>
- iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
+ BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
{ return this->base_t::insert_equal(p, ::boost::forward<KeyType>(x)); }
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
diff --git a/boost/container/small_vector.hpp b/boost/container/small_vector.hpp
index 14446247ac..804740cc72 100644
--- a/boost/container/small_vector.hpp
+++ b/boost/container/small_vector.hpp
@@ -387,8 +387,8 @@ class small_vector_base
this->steal_resources(x);
}
else{
- this->assign( boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.begin()))
- , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.end ()))
+ this->assign( boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.begin()))
+ , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.end ()))
);
}
}
diff --git a/boost/container/stable_vector.hpp b/boost/container/stable_vector.hpp
index 5d6dc0f228..cf156e04de 100644
--- a/boost/container/stable_vector.hpp
+++ b/boost/container/stable_vector.hpp
@@ -44,7 +44,7 @@
#include <boost/container/detail/iterator.hpp>
#include <boost/container/detail/iterators.hpp>
#include <boost/container/detail/placement_new.hpp>
-#include <boost/container/detail/to_raw_pointer.hpp>
+#include <boost/move/detail/to_raw_pointer.hpp>
#include <boost/container/detail/type_traits.hpp>
// intrusive
#include <boost/intrusive/pointer_traits.hpp>
@@ -1975,7 +1975,7 @@ class stable_vector
, container_detail::addressof(p->value)
, it);
//This does not throw
- ::new(static_cast<node_base_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t())
+ ::new(static_cast<node_base_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t())
node_base_type(index_traits_type::ptr_to_node_base_ptr(*up_index));
}
@@ -1988,7 +1988,7 @@ class stable_vector
, container_detail::addressof(p->value)
, ::boost::forward<ValueConvertible>(value_convertible));
//This does not throw
- ::new(static_cast<node_base_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) node_base_type;
+ ::new(static_cast<node_base_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) node_base_type;
}
void priv_swap_members(stable_vector &x)
diff --git a/boost/container/string.hpp b/boost/container/string.hpp
index 7b780fd588..24056781c9 100644
--- a/boost/container/string.hpp
+++ b/boost/container/string.hpp
@@ -35,10 +35,11 @@
#include <boost/container/detail/min_max.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/next_capacity.hpp>
-#include <boost/container/detail/to_raw_pointer.hpp>
+#include <boost/move/detail/to_raw_pointer.hpp>
#include <boost/container/detail/version_type.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/minimal_char_traits_header.hpp>
+#include <boost/container/detail/algorithm.hpp>
#include <boost/intrusive/pointer_traits.hpp>
@@ -51,7 +52,6 @@
#include <boost/functional/hash.hpp>
#include <algorithm>
-#include <functional> //bind2nd, etc.
#include <iosfwd>
#include <istream>
#include <ostream>
@@ -308,14 +308,14 @@ class basic_string_base
{
allocator_traits_type::construct
( this->alloc()
- , container_detail::to_raw_pointer(p)
+ , boost::movelib::to_raw_pointer(p)
, value
);
}
void destroy(pointer p, size_type n)
{
- value_type *raw_p = container_detail::to_raw_pointer(p);
+ value_type *raw_p = boost::movelib::to_raw_pointer(p);
for(; n--; ++raw_p){
allocator_traits_type::destroy( this->alloc(), raw_p);
}
@@ -325,7 +325,7 @@ class basic_string_base
{
allocator_traits_type::destroy
( this->alloc()
- , container_detail::to_raw_pointer(p)
+ , boost::movelib::to_raw_pointer(p)
);
}
@@ -541,8 +541,8 @@ class basic_string
bool operator()(const typename Tr::char_type& x) const
{
- return std::find_if(m_first, m_last,
- std::bind1st(Eq_traits<Tr>(), x)) == m_last;
+ return boost::container::find_if(m_first, m_last,
+ boost::container::bind1st(Eq_traits<Tr>(), x)) == m_last;
}
};
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -1158,8 +1158,8 @@ class basic_string
size_type long_storage = this->priv_long_storage();
size_type long_size = this->priv_long_size();
//Shrink from allocated buffer to the internal one, including trailing null
- Traits::copy( container_detail::to_raw_pointer(this->priv_short_addr())
- , container_detail::to_raw_pointer(long_addr)
+ Traits::copy( boost::movelib::to_raw_pointer(this->priv_short_addr())
+ , boost::movelib::to_raw_pointer(long_addr)
, long_size+1);
this->is_short(true);
this->alloc().deallocate(long_addr, long_storage);
@@ -1492,7 +1492,7 @@ class basic_string
{
size_type n = static_cast<size_type>(last - first);
this->reserve(n);
- CharT* ptr = container_detail::to_raw_pointer(this->priv_addr());
+ CharT* ptr = boost::movelib::to_raw_pointer(this->priv_addr());
Traits::copy(ptr, first, n);
this->priv_construct_null(ptr + n);
this->priv_size(n);
@@ -1511,7 +1511,7 @@ class basic_string
{
size_type cur = 0;
const pointer addr = this->priv_addr();
- CharT *ptr = container_detail::to_raw_pointer(addr);
+ CharT *ptr = boost::movelib::to_raw_pointer(addr);
const size_type old_size = this->priv_size();
while (first != last && cur != old_size) {
Traits::assign(*ptr, *first);
@@ -1570,7 +1570,7 @@ class basic_string
size_type len = container_detail::min_value(n, str_size - pos2);
if (sz > this->max_size() - len)
throw_length_error("basic_string::insert max_size() exceeded");
- const CharT *beg_ptr = container_detail::to_raw_pointer(s.begin()) + pos2;
+ const CharT *beg_ptr = boost::movelib::to_raw_pointer(s.begin()) + pos2;
const CharT *end_ptr = beg_ptr + len;
this->insert(this->priv_addr() + pos1, beg_ptr, end_ptr);
return *this;
@@ -1730,10 +1730,10 @@ class basic_string
pointer_past_last, pointer_past_last);
this->priv_size(old_size+n);
- Traits::move(const_cast<CharT*>(container_detail::to_raw_pointer(p + n)),
- container_detail::to_raw_pointer(p),
+ Traits::move(const_cast<CharT*>(boost::movelib::to_raw_pointer(p + n)),
+ boost::movelib::to_raw_pointer(p),
(elems_after - n) + 1);
- this->priv_copy(first, last, const_cast<CharT*>(container_detail::to_raw_pointer(p)));
+ this->priv_copy(first, last, const_cast<CharT*>(boost::movelib::to_raw_pointer(p)));
}
else {
ForwardIter mid = first;
@@ -1746,7 +1746,7 @@ class basic_string
(p, const_iterator(old_start + old_length + 1),
old_start + newer_size);
this->priv_size(newer_size + elems_after);
- this->priv_copy(first, mid, const_cast<CharT*>(container_detail::to_raw_pointer(p)));
+ this->priv_copy(first, mid, const_cast<CharT*>(boost::movelib::to_raw_pointer(p)));
}
}
else{
@@ -1773,9 +1773,9 @@ class basic_string
else{
//value_type is POD, so backwards expansion is much easier
//than with vector<T>
- value_type * const oldbuf = container_detail::to_raw_pointer(old_start);
- value_type * const newbuf = container_detail::to_raw_pointer(new_start);
- const value_type *const pos = container_detail::to_raw_pointer(p);
+ value_type * const oldbuf = boost::movelib::to_raw_pointer(old_start);
+ value_type * const newbuf = boost::movelib::to_raw_pointer(new_start);
+ const value_type *const pos = boost::movelib::to_raw_pointer(p);
const size_type before = pos - oldbuf;
//First move old data
@@ -1847,10 +1847,10 @@ class basic_string
iterator erase(const_iterator p) BOOST_NOEXCEPT_OR_NOTHROW
{
// The move includes the terminating null.
- CharT * const ptr = const_cast<CharT*>(container_detail::to_raw_pointer(p));
+ CharT * const ptr = const_cast<CharT*>(boost::movelib::to_raw_pointer(p));
const size_type old_size = this->priv_size();
Traits::move(ptr,
- container_detail::to_raw_pointer(p + 1),
+ boost::movelib::to_raw_pointer(p + 1),
old_size - (p - this->priv_addr()));
this->priv_size(old_size-1);
return iterator(ptr);
@@ -1866,12 +1866,12 @@ class basic_string
//! the other elements being erased. If no such element exists, end() is returned.
iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW
{
- CharT * f = const_cast<CharT*>(container_detail::to_raw_pointer(first));
+ CharT * f = const_cast<CharT*>(boost::movelib::to_raw_pointer(first));
if (first != last) { // The move includes the terminating null.
const size_type num_erased = last - first;
const size_type old_size = this->priv_size();
Traits::move(f,
- container_detail::to_raw_pointer(last),
+ boost::movelib::to_raw_pointer(last),
(old_size + 1)-(last - this->priv_addr()));
const size_type new_length = old_size - num_erased;
this->priv_size(new_length);
@@ -2059,11 +2059,11 @@ class basic_string
{
const size_type len = static_cast<size_type>(i2 - i1);
if (len >= n) {
- Traits::assign(const_cast<CharT*>(container_detail::to_raw_pointer(i1)), n, c);
+ Traits::assign(const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)), n, c);
erase(i1 + n, i2);
}
else {
- Traits::assign(const_cast<CharT*>(container_detail::to_raw_pointer(i1)), len, c);
+ Traits::assign(const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)), len, c);
insert(i2, n - len, c);
}
return *this;
@@ -2088,7 +2088,7 @@ class basic_string
)
{
for ( ; i1 != i2 && j1 != j2; ++i1, ++j1){
- Traits::assign(*const_cast<CharT*>(container_detail::to_raw_pointer(i1)), *j1);
+ Traits::assign(*const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)), *j1);
}
if (j1 == j2)
@@ -2111,13 +2111,13 @@ class basic_string
difference_type n = boost::container::iterator_distance(j1, j2);
const difference_type len = i2 - i1;
if (len >= n) {
- this->priv_copy(j1, j2, const_cast<CharT*>(container_detail::to_raw_pointer(i1)));
+ this->priv_copy(j1, j2, const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)));
this->erase(i1 + n, i2);
}
else {
ForwardIter m = j1;
boost::container::iterator_advance(m, len);
- this->priv_copy(j1, m, const_cast<CharT*>(container_detail::to_raw_pointer(i1)));
+ this->priv_copy(j1, m, const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)));
this->insert(i2, m, j2);
}
return *this;
@@ -2128,7 +2128,7 @@ class basic_string
//!
//! <b>Effects</b>: Calls `replace(i1 - begin(), i2 - i1, sv).`.
//!
- //! <bReturns</b>: *this.
+ //! <b>Returns</b>: *this.
template<template <class, class> class BasicStringView>
basic_string& replace(const_iterator i1, const_iterator i2, BasicStringView<CharT, Traits> sv)
{
@@ -2141,7 +2141,7 @@ class basic_string
//!
//! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, il.begin(), il.size()).
//!
- //! <bReturns</b>: *this.
+ //! <b>Returns</b>: *this.
basic_string& replace(const_iterator i1, const_iterator i2, std::initializer_list<CharT> il)
{
return this->replace( static_cast<size_type>(i1 - this->cbegin())
@@ -2166,7 +2166,7 @@ class basic_string
if (pos > this->size())
throw_out_of_range("basic_string::copy out of range position");
const size_type len = container_detail::min_value(n, this->size() - pos);
- Traits::copy(s, container_detail::to_raw_pointer(this->priv_addr() + pos), len);
+ Traits::copy(s, boost::movelib::to_raw_pointer(this->priv_addr() + pos), len);
return len;
}
@@ -2195,7 +2195,7 @@ class basic_string
//!
//! <b>Complexity</b>: constant time.
const CharT* c_str() const BOOST_NOEXCEPT_OR_NOTHROW
- { return container_detail::to_raw_pointer(this->priv_addr()); }
+ { return boost::movelib::to_raw_pointer(this->priv_addr()); }
//! <b>Requires</b>: The program shall not alter any of the values stored in the character array.
//!
@@ -2203,13 +2203,13 @@ class basic_string
//!
//! <b>Complexity</b>: constant time.
const CharT* data() const BOOST_NOEXCEPT_OR_NOTHROW
- { return container_detail::to_raw_pointer(this->priv_addr()); }
+ { return boost::movelib::to_raw_pointer(this->priv_addr()); }
//! <b>Returns</b>: A pointer p such that p + i == &operator[](i) for each i in [0,size()].
//!
//! <b>Complexity</b>: constant time.
CharT* data() BOOST_NOEXCEPT_OR_NOTHROW
- { return container_detail::to_raw_pointer(this->priv_addr()); }
+ { return boost::movelib::to_raw_pointer(this->priv_addr()); }
#ifndef BOOST_CONTAINER_TEMPLATED_CONVERSION_OPERATOR_BROKEN
//! <b>Returns</b>: a string_view to the characters in the string.
@@ -2272,8 +2272,8 @@ class basic_string
const pointer addr = this->priv_addr();
pointer finish = addr + this->priv_size();
const const_iterator result =
- std::search(container_detail::to_raw_pointer(addr + pos),
- container_detail::to_raw_pointer(finish),
+ boost::container::search(boost::movelib::to_raw_pointer(addr + pos),
+ boost::movelib::to_raw_pointer(finish),
s, s + n, Eq_traits<Traits>());
return result != finish ? result - begin() : npos;
}
@@ -2299,8 +2299,8 @@ class basic_string
const pointer addr = this->priv_addr();
pointer finish = addr + sz;
const const_iterator result =
- std::find_if(addr + pos, finish,
- std::bind2nd(Eq_traits<Traits>(), c));
+ boost::container::find_if(addr + pos, finish,
+ boost::container::bind2nd(Eq_traits<Traits>(), c));
return result != finish ? result - begin() : npos;
}
}
@@ -2371,8 +2371,8 @@ class basic_string
else {
const const_iterator last = begin() + container_detail::min_value(len - 1, pos) + 1;
const_reverse_iterator rresult =
- std::find_if(const_reverse_iterator(last), rend(),
- std::bind2nd(Eq_traits<Traits>(), c));
+ boost::container::find_if(const_reverse_iterator(last), rend(),
+ boost::container::bind2nd(Eq_traits<Traits>(), c));
return rresult != rend() ? (rresult.base() - 1) - begin() : npos;
}
}
@@ -2385,7 +2385,7 @@ class basic_string
//!
//! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
size_type find_first_of(const basic_string& str, size_type pos = 0) const
- { return find_first_of(str.c_str(), pos, str.size()); }
+ { return this->find_first_of(str.c_str(), pos, str.size()); }
//! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both of the
//! following conditions obtain: a) pos <= xpos and xpos < size();
@@ -2396,7 +2396,7 @@ class basic_string
//! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
template<template <class, class> class BasicStringView>
size_type find_first_of(BasicStringView<CharT, Traits> sv, size_type pos = 0) const
- { return find_first_of(sv.data(), pos, sv.size()); }
+ { return this->find_first_of(sv.data(), pos, sv.size()); }
//! <b>Requires</b>: s points to an array of at least n elements of CharT.
//!
@@ -2411,7 +2411,7 @@ class basic_string
else {
const pointer addr = this->priv_addr();
pointer finish = addr + sz;
- const_iterator result = std::find_first_of
+ const_iterator result = boost::container::find_first_of
(addr + pos, finish, s, s + n, Eq_traits<Traits>());
return result != finish ? result - this->begin() : npos;
}
@@ -2423,7 +2423,7 @@ class basic_string
//!
//! <b>Returns</b>: find_first_of(basic_string(s), pos).
size_type find_first_of(const CharT* s, size_type pos = 0) const
- { return find_first_of(s, pos, Traits::length(s)); }
+ { return this->find_first_of(s, pos, Traits::length(s)); }
//! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
//!
@@ -2431,7 +2431,7 @@ class basic_string
//!
//! <b>Returns</b>: find_first_of(basic_string<CharT,traits,Allocator>(1,c), pos).
size_type find_first_of(CharT c, size_type pos = 0) const
- { return find(c, pos); }
+ { return this->find(c, pos); }
//! <b>Effects</b>: Determines the highest position xpos, if possible, such that both of
//! the following conditions obtain: a) xpos <= pos and xpos < size(); b)
@@ -2441,7 +2441,7 @@ class basic_string
//!
//! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
size_type find_last_of(const basic_string& str, size_type pos = npos) const
- { return find_last_of(str.c_str(), pos, str.size()); }
+ { return this->find_last_of(str.c_str(), pos, str.size()); }
//! <b>Effects</b>: Determines the highest position xpos, if possible, such that both of
//! the following conditions obtain: a) xpos <= pos and xpos < size(); b)
@@ -2452,7 +2452,7 @@ class basic_string
//! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
template<template <class, class> class BasicStringView>
size_type find_last_of(BasicStringView<CharT, Traits> sv, size_type pos = npos) const
- { return find_last_of(sv.data(), pos, sv.size()); }
+ { return this->find_last_of(sv.data(), pos, sv.size()); }
//! <b>Requires</b>: s points to an array of at least n elements of CharT.
//!
@@ -2469,7 +2469,7 @@ class basic_string
const pointer addr = this->priv_addr();
const const_iterator last = addr + container_detail::min_value(len - 1, pos) + 1;
const const_reverse_iterator rresult =
- std::find_first_of(const_reverse_iterator(last), rend(),
+ boost::container::find_first_of(const_reverse_iterator(last), rend(),
s, s + n, Eq_traits<Traits>());
return rresult != rend() ? (rresult.base() - 1) - addr : npos;
}
@@ -2524,7 +2524,7 @@ class basic_string
else {
const pointer addr = this->priv_addr();
const pointer finish = addr + this->priv_size();
- const const_iterator result = std::find_if
+ const const_iterator result = boost::container::find_if
(addr + pos, finish, Not_within_traits<Traits>(s, s + n));
return result != finish ? result - addr : npos;
}
@@ -2549,8 +2549,8 @@ class basic_string
const pointer addr = this->priv_addr();
const pointer finish = addr + this->priv_size();
const const_iterator result
- = std::find_if(addr + pos, finish,
- std::not1(std::bind2nd(Eq_traits<Traits>(), c)));
+ = boost::container::find_if(addr + pos, finish,
+ boost::container::not1(boost::container::bind2nd(Eq_traits<Traits>(), c)));
return result != finish ? result - begin() : npos;
}
}
@@ -2590,7 +2590,7 @@ class basic_string
else {
const const_iterator last = begin() + container_detail::min_value(len - 1, pos) + 1;
const const_reverse_iterator rresult =
- std::find_if(const_reverse_iterator(last), rend(),
+ boost::container::find_if(const_reverse_iterator(last), rend(),
Not_within_traits<Traits>(s, s + n));
return rresult != rend() ? (rresult.base() - 1) - begin() : npos;
}
@@ -2616,8 +2616,8 @@ class basic_string
else {
const const_iterator last = begin() + container_detail::min_value(len - 1, pos) + 1;
const const_reverse_iterator rresult =
- std::find_if(const_reverse_iterator(last), rend(),
- std::not1(std::bind2nd(Eq_traits<Traits>(), c)));
+ boost::container::find_if(const_reverse_iterator(last), rend(),
+ boost::container::not1(boost::container::bind2nd(Eq_traits<Traits>(), c)));
return rresult != rend() ? (rresult.base() - 1) - begin() : npos;
}
}
@@ -2804,8 +2804,8 @@ class basic_string
{
const difference_type n1 = l1 - f1;
const difference_type n2 = l2 - f2;
- const int cmp = Traits::compare(container_detail::to_raw_pointer(f1),
- container_detail::to_raw_pointer(f2),
+ const int cmp = Traits::compare(boost::movelib::to_raw_pointer(f1),
+ boost::movelib::to_raw_pointer(f2),
container_detail::min_value(n1, n2));
return cmp != 0 ? cmp : (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0));
}
@@ -2826,8 +2826,8 @@ class basic_string
real_cap = long_size+1;
const pointer ret = this->allocation_command(allocate_new, long_size+1, real_cap, reuse);
//Copy and update
- Traits::copy( container_detail::to_raw_pointer(ret)
- , container_detail::to_raw_pointer(this->priv_long_addr())
+ Traits::copy( boost::movelib::to_raw_pointer(ret)
+ , boost::movelib::to_raw_pointer(this->priv_long_addr())
, long_size+1);
this->priv_long_addr(ret);
this->priv_storage(real_cap);
diff --git a/boost/container/vector.hpp b/boost/container/vector.hpp
index 336d616007..5ec669ba99 100644
--- a/boost/container/vector.hpp
+++ b/boost/container/vector.hpp
@@ -36,10 +36,10 @@
#include <boost/container/detail/destroyers.hpp>
#include <boost/container/detail/iterator.hpp>
#include <boost/container/detail/iterators.hpp>
-#include <boost/container/detail/iterator_to_raw_pointer.hpp>
+#include <boost/move/detail/iterator_to_raw_pointer.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/next_capacity.hpp>
-#include <boost/container/detail/to_raw_pointer.hpp>
+#include <boost/move/detail/to_raw_pointer.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/version_type.hpp>
// intrusive
@@ -54,6 +54,10 @@
#include <boost/move/detail/fwd_macros.hpp>
#endif
#include <boost/move/detail/move_helpers.hpp>
+// move/algo
+#include <boost/move/algo/adaptive_merge.hpp>
+#include <boost/move/algo/unique.hpp>
+#include <boost/move/algo/predicate.hpp>
// other
#include <boost/core/no_exceptions_support.hpp>
#include <boost/assert.hpp>
@@ -609,7 +613,7 @@ struct vector_alloc_holder<Allocator, version_0>
, m_size(holder.m_size) //Size is initialized here so vector should only call uninitialized_xxx after this
{
::boost::container::uninitialized_move_alloc_n
- (this->alloc(), container_detail::to_raw_pointer(holder.start()), m_size, container_detail::to_raw_pointer(this->start()));
+ (this->alloc(), boost::movelib::to_raw_pointer(holder.start()), m_size, boost::movelib::to_raw_pointer(this->start()));
}
template<class OtherAllocator, class OtherAllocatorVersion>
@@ -621,7 +625,7 @@ struct vector_alloc_holder<Allocator, version_0>
const size_type n = holder.m_size;
this->priv_first_allocation(n);
::boost::container::uninitialized_move_alloc_n
- (this->alloc(), container_detail::to_raw_pointer(holder.start()), n, container_detail::to_raw_pointer(this->start()));
+ (this->alloc(), boost::movelib::to_raw_pointer(holder.start()), n, boost::movelib::to_raw_pointer(this->start()));
}
BOOST_CONTAINER_FORCEINLINE void priv_first_allocation(size_type cap)
@@ -675,8 +679,8 @@ struct vector_alloc_holder<Allocator, version_0>
void priv_deep_swap(vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> &x)
{
const size_type MaxTmpStorage = sizeof(value_type)*Allocator::internal_capacity;
- value_type *const first_this = container_detail::to_raw_pointer(this->start());
- value_type *const first_x = container_detail::to_raw_pointer(x.start());
+ value_type *const first_this = boost::movelib::to_raw_pointer(this->start());
+ value_type *const first_x = boost::movelib::to_raw_pointer(x.start());
if(this->m_size < x.m_size){
boost::container::deep_swap_alloc_n<MaxTmpStorage>(this->alloc(), first_this, this->m_size, first_x, x.m_size);
@@ -1186,7 +1190,7 @@ class vector
if (first == last){
//There are no more elements in the sequence, erase remaining
T* const end_pos = this->priv_raw_end();
- const size_type n = static_cast<size_type>(end_pos - container_detail::iterator_to_raw_pointer(cur));
+ const size_type n = static_cast<size_type>(end_pos - boost::movelib::iterator_to_raw_pointer(cur));
this->priv_destroy_last_n(n);
}
else{
@@ -2005,7 +2009,7 @@ class vector
{
BOOST_ASSERT(this->priv_in_range(position));
const pointer p = vector_iterator_get_ptr(position);
- T *const pos_ptr = container_detail::to_raw_pointer(p);
+ T *const pos_ptr = boost::movelib::to_raw_pointer(p);
T *const beg_ptr = this->priv_raw_begin();
T *const new_end_ptr = ::boost::container::move(pos_ptr + 1, beg_ptr + this->m_holder.m_size, pos_ptr);
//Move elements forward and destroy last
@@ -2025,9 +2029,9 @@ class vector
(first < last && this->priv_in_range(first) && this->priv_in_range_or_end(last)));
if (first != last){
T* const old_end_ptr = this->priv_raw_end();
- T* const first_ptr = container_detail::to_raw_pointer(vector_iterator_get_ptr(first));
- T* const last_ptr = container_detail::to_raw_pointer(vector_iterator_get_ptr(last));
- T* const ptr = container_detail::to_raw_pointer(boost::container::move(last_ptr, old_end_ptr, first_ptr));
+ T* const first_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(first));
+ T* const last_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(last));
+ T* const ptr = boost::movelib::to_raw_pointer(boost::container::move(last_ptr, old_end_ptr, first_ptr));
this->priv_destroy_last_n(old_end_ptr - ptr);
}
return iterator(vector_iterator_get_ptr(first));
@@ -2240,37 +2244,15 @@ class vector
p = this->m_holder.allocation_command(allocate_new, new_size, new_cap, p);
this->priv_merge_in_new_buffer(UniqueBool(), first, n, comp, p, new_cap);
}
- else if(!UniqueBool::value && free_c >= n){
- typedef container_detail::vector_merge_cursor<T, size_type, BidirIt, Compare> inserter_t;
- T* const pbeg = this->priv_raw_begin();
- return this->priv_insert_ordered_at(n, inserter_t(pbeg, pbeg + s, last, comp));
- }
- else{ //UniqueBool::value == true and free_c >= n
- std::size_t remaining = n;
- static const std::size_t PosCount = 64u;
- size_type positions[PosCount];
- size_type *indexes = 0;
- while(remaining){
- //Query for room to store indexes in the remaining buffer
- boost::uintptr_t const szt_align_mask = container_detail::alignment_of<size_type>::value - 1;
- boost::uintptr_t const addr = boost::uintptr_t(this->priv_raw_begin() + s + n);
- boost::uintptr_t const capaddr = boost::uintptr_t(this->priv_raw_begin() + c);
- boost::uintptr_t const aligned_addr = (addr + szt_align_mask) & ~szt_align_mask;
- indexes = reinterpret_cast<size_type *>(aligned_addr);
- std::size_t index_capacity = (aligned_addr >= capaddr) ? 0u : (capaddr - aligned_addr)/sizeof(size_type);
-
- //Capacity is constant, we're not going to change it
- if(index_capacity < PosCount){
- indexes = positions;
- index_capacity = PosCount;
- }
- if(index_capacity > remaining)
- index_capacity = remaining;
- BidirIt limit = first;
- boost::container::iterator_advance(limit, index_capacity);
- this->priv_insert_ordered_range(UniqueBool(), index_capacity, first, limit, indexes, comp);
- first = limit;
- remaining -= index_capacity;
+ else{
+ T *raw_pos = boost::movelib::iterator_to_raw_pointer(this->insert(this->cend(), first, last));
+ T *raw_beg = this->priv_raw_begin();
+ T *raw_end = this->priv_raw_end();
+ boost::movelib::adaptive_merge(raw_beg, raw_pos, raw_end, comp, raw_end, free_c - n);
+ if(UniqueBool::value){
+ size_type const count =
+ static_cast<size_type>(raw_end - boost::movelib::unique(raw_beg, raw_end, boost::movelib::negate<Compare>(comp)));
+ this->priv_destroy_last_n(count);
}
}
}
@@ -2279,53 +2261,6 @@ class vector
}
}
- template <class UniqueBool, class BidirIt, class Compare>
- void priv_insert_ordered_range
- (UniqueBool, size_type const n, BidirIt first, BidirIt const last, size_type positions[], Compare comp)
- {
- //Linear: at most N + M -1 comparisons
- //Log: MlogN
- //Average
- //Linear: N + M - 2
- //Log: MlogN
- //N+M - 2
- //N
- //(N+M)/2 < MlogN
- //(N/M+1)/2 <= logN
- //bool const linear = !s || !n || (s <= n) || ((s+n)/n/2 < logN);
- size_type const s = this->size();
- size_type remaining = n;
- T* const pbeg = this->priv_raw_begin();
- T* const pend = pbeg + s;
- T* pcur = pbeg;
- size_type *position = positions;
- size_type added_in_middle = 0;
- if(first != last && pcur != pend){
- while(1){
- //maintain stability moving external values only if they are strictly less
- if(comp(*first, *pcur)) {
- *position = static_cast<size_type>(pcur - pbeg);
- BOOST_ASSERT((position == positions) || (*(position-1) == size_type(-1)) || (*(position-1) <= *position));
- ++position;
- ++added_in_middle;
- --remaining;
- if(++first == last) break;
- }
- else if(UniqueBool::value && !comp(*pcur, *first)){
- *position = size_type(-1);
- ++position;
- --remaining;
- if(++first == last) break;
- }
- else{
- if(++pcur == pend) break;
- }
- }
- }
- this->insert_ordered_at(added_in_middle, position, first);
- this->insert(this->cend(), remaining, first, last);
- }
-
template<class UniqueBool, class FwdIt, class Compare>
void priv_merge_in_new_buffer
(UniqueBool, FwdIt first, size_type n, Compare comp, pointer new_storage, size_type const new_cap)
@@ -2337,7 +2272,7 @@ class vector
T* pbeg = this->priv_raw_begin();
size_type const old_size = this->size();
T* const pend = pbeg + old_size;
- T* d_first = container_detail::to_raw_pointer(new_storage);
+ T* d_first = boost::movelib::to_raw_pointer(new_storage);
size_type added = n;
//Merge in new buffer loop
while(1){
@@ -2373,7 +2308,7 @@ class vector
//Nothrow operations
pointer const old_p = this->m_holder.start();
size_type const old_cap = this->m_holder.capacity();
- boost::container::destroy_alloc_n(a, container_detail::to_raw_pointer(old_p), old_size);
+ boost::container::destroy_alloc_n(a, boost::movelib::to_raw_pointer(old_p), old_size);
a.deallocate(old_p, old_cap);
this->m_holder.m_size = old_size + added;
this->m_holder.start(new_storage);
@@ -2444,8 +2379,8 @@ class vector
}
//Else do a one by one move
else{
- this->assign( boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.begin()))
- , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.end() ))
+ this->assign( boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.begin()))
+ , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.end() ))
);
}
//Move allocator if needed
@@ -2514,8 +2449,8 @@ class vector
}
//... and move-insert the remaining range
sml.insert( sml.cend()
- , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(big.nth(common_elements)))
- , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(big.end()))
+ , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(big.nth(common_elements)))
+ , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(big.end()))
);
//Destroy remaining elements
big.erase(big.nth(common_elements), big.cend());
@@ -2540,7 +2475,7 @@ class vector
pointer const p = allocator_traits_type::allocate(this->m_holder.alloc(), new_cap, this->m_holder.m_start);
//We will reuse insert code, so create a dummy input iterator
this->priv_forward_range_insert_new_allocation
- ( container_detail::to_raw_pointer(p), new_cap, this->priv_raw_end(), 0, this->priv_dummy_empty_proxy());
+ ( boost::movelib::to_raw_pointer(p), new_cap, this->priv_raw_end(), 0, this->priv_dummy_empty_proxy());
}
void priv_reserve_no_capacity(size_type new_cap, version_2)
@@ -2561,7 +2496,7 @@ class vector
this->m_holder.capacity(real_cap);
}
else{ //If there is no forward expansion, move objects, we will reuse insertion code
- T * const new_mem = container_detail::to_raw_pointer(ret);
+ T * const new_mem = boost::movelib::to_raw_pointer(ret);
T * const ins_pos = this->priv_raw_end();
if(reuse){ //Backwards (and possibly forward) expansion
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
@@ -2691,7 +2626,7 @@ class vector
++this->num_alloc;
#endif
this->priv_forward_range_insert_new_allocation
- ( container_detail::to_raw_pointer(p), sz
+ ( boost::movelib::to_raw_pointer(p), sz
, this->priv_raw_begin(), 0, this->priv_dummy_empty_proxy());
}
}
@@ -2735,11 +2670,11 @@ class vector
{
//Check if we have enough memory or try to expand current memory
const size_type n_pos = pos - this->m_holder.start();
- T *const raw_pos = container_detail::to_raw_pointer(pos);
+ T *const raw_pos = boost::movelib::to_raw_pointer(pos);
const size_type new_cap = this->m_holder.next_capacity(n);
//Pass the hint so that allocators can take advantage of this.
- T * const new_buf = container_detail::to_raw_pointer
+ T * const new_buf = boost::movelib::to_raw_pointer
(allocator_traits_type::allocate(this->m_holder.alloc(), new_cap, this->m_holder.m_start));
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
++this->num_alloc;
@@ -2754,7 +2689,7 @@ class vector
(const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, version_2)
{
//Check if we have enough memory or try to expand current memory
- T *const raw_pos = container_detail::to_raw_pointer(pos);
+ T *const raw_pos = boost::movelib::to_raw_pointer(pos);
const size_type n_pos = raw_pos - this->priv_raw_begin();
//There is not enough memory, allocate a new
@@ -2781,7 +2716,7 @@ class vector
++this->num_expand_bwd;
#endif
this->priv_forward_range_insert_expand_backwards
- (container_detail::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
+ (boost::movelib::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
}
}
//New buffer
@@ -2790,7 +2725,7 @@ class vector
++this->num_alloc;
#endif
this->priv_forward_range_insert_new_allocation
- ( container_detail::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
+ ( boost::movelib::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
}
return iterator(this->m_holder.start() + n_pos);
@@ -2810,7 +2745,7 @@ class vector
}
else{
//Expand forward
- T *const raw_pos = container_detail::to_raw_pointer(pos);
+ T *const raw_pos = boost::movelib::to_raw_pointer(pos);
const size_type n_pos = raw_pos - this->priv_raw_begin();
this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
return iterator(this->m_holder.start() + n_pos);
@@ -2926,10 +2861,10 @@ class vector
}
private:
- T *priv_raw_begin() const
- { return container_detail::to_raw_pointer(m_holder.start()); }
+ BOOST_CONTAINER_FORCEINLINE T *priv_raw_begin() const
+ { return boost::movelib::to_raw_pointer(m_holder.start()); }
- T* priv_raw_end() const
+ BOOST_CONTAINER_FORCEINLINE T* priv_raw_end() const
{ return this->priv_raw_begin() + this->m_holder.m_size; }
template <class InsertionProxy>
diff --git a/boost/context/continuation.hpp b/boost/context/continuation.hpp
index 6a50713158..8db62a9506 100644
--- a/boost/context/continuation.hpp
+++ b/boost/context/continuation.hpp
@@ -4,551 +4,10 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_CONTEXT_CONTINUATION_H
-#define BOOST_CONTEXT_CONTINUATION_H
-
-#include <boost/context/detail/config.hpp>
-
-#include <algorithm>
-#include <cstddef>
-#include <cstdint>
-#include <cstdlib>
-#include <exception>
-#include <functional>
-#include <memory>
-#include <ostream>
-#include <tuple>
-#include <utility>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/intrusive_ptr.hpp>
-
-#if defined(BOOST_NO_CXX17_STD_APPLY)
-#include <boost/context/detail/apply.hpp>
-#endif
-#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
-#include <boost/context/detail/exchange.hpp>
-#endif
-#if defined(BOOST_NO_CXX17_STD_INVOKE)
-#include <boost/context/detail/invoke.hpp>
-#endif
-#include <boost/context/detail/disable_overload.hpp>
-#include <boost/context/detail/exception.hpp>
-#include <boost/context/detail/fcontext.hpp>
-#include <boost/context/detail/tuple.hpp>
-#include <boost/context/fixedsize_stack.hpp>
-#include <boost/context/flags.hpp>
-#include <boost/context/preallocated.hpp>
-#include <boost/context/segmented_stack.hpp>
-#include <boost/context/stack_context.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-#if defined(BOOST_MSVC)
-# pragma warning(push)
-# pragma warning(disable: 4702)
-#endif
-
-namespace boost {
-namespace context {
-namespace detail {
-
-template< int N >
-struct helper {
- template< typename T >
- static T convert( T && t) noexcept {
- return std::forward< T >( t);
- }
-};
-
-template<>
-struct helper< 1 > {
- template< typename T >
- static std::tuple< T > convert( T && t) noexcept {
- return std::make_tuple( std::forward< T >( t) );
- }
-};
-
-inline
-transfer_t context_unwind( transfer_t t) {
- throw forced_unwind( t.fctx);
- return { nullptr, nullptr };
-}
-
-template< typename Rec >
-transfer_t context_exit( transfer_t t) noexcept {
- Rec * rec = static_cast< Rec * >( t.data);
- // destroy context stack
- rec->deallocate();
- return { nullptr, nullptr };
-}
-
-template< typename Rec >
-void context_entry( transfer_t t_) noexcept {
- // transfer control structure to the context-stack
- Rec * rec = static_cast< Rec * >( t_.data);
- BOOST_ASSERT( nullptr != t_.fctx);
- BOOST_ASSERT( nullptr != rec);
- transfer_t t = { nullptr, nullptr };
- try {
- // jump back to `context_create()`
- t = jump_fcontext( t_.fctx, nullptr);
- // start executing
- t = rec->run( t);
- } catch ( forced_unwind const& e) {
- t = { e.fctx, nullptr };
- }
- BOOST_ASSERT( nullptr != t.fctx);
- // destroy context-stack of `this`context on next context
- ontop_fcontext( t.fctx, rec, context_exit< Rec >);
- BOOST_ASSERT_MSG( false, "context already terminated");
-}
-
-template<
- typename Ctx,
- typename StackAlloc,
- typename Fn
->
-class record {
-private:
- StackAlloc salloc_;
- stack_context sctx_;
- typename std::decay< Fn >::type fn_;
-
- static void destroy( record * p) noexcept {
- StackAlloc salloc = p->salloc_;
- stack_context sctx = p->sctx_;
- // deallocate record
- p->~record();
- // destroy stack with stack allocator
- salloc.deallocate( sctx);
- }
-
-public:
- record( stack_context sctx, StackAlloc const& salloc,
- Fn && fn) noexcept :
- salloc_( salloc),
- sctx_( sctx),
- fn_( std::forward< Fn >( fn) ) {
- }
-
- record( record const&) = delete;
- record & operator=( record const&) = delete;
-
- void deallocate() noexcept {
- destroy( this);
- }
-
- transfer_t run( transfer_t t) {
- Ctx from{ t };
- // invoke context-function
-#if defined(BOOST_NO_CXX17_STD_INVOKE)
- Ctx cc = invoke( fn_, std::move( from) );
-#else
- Ctx cc = std::invoke( fn_, std::move( from) );
-#endif
-#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
- return { exchange( cc.t_.fctx, nullptr), nullptr };
+#if defined(BOOST_USE_UCONTEXT)
+#include <boost/context/continuation_ucontext.hpp>
+#elif defined(BOOST_USE_WINFIB)
+#include <boost/context/continuation_winfib.hpp>
#else
- return { std::exchange( cc.t_.fctx, nullptr), nullptr };
+#include <boost/context/continuation_fcontext.hpp>
#endif
- }
-};
-
-template< typename Record, typename StackAlloc, typename Fn >
-fcontext_t context_create( StackAlloc salloc, Fn && fn) {
- auto sctx = salloc.allocate();
- // reserve space for control structure
-#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
- const std::size_t size = sctx.size - sizeof( Record);
- void * sp = static_cast< char * >( sctx.sp) - sizeof( Record);
-#else
- constexpr std::size_t func_alignment = 64; // alignof( Record);
- constexpr std::size_t func_size = sizeof( Record);
- // reserve space on stack
- void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
- // align sp pointer
- std::size_t space = func_size + func_alignment;
- sp = std::align( func_alignment, func_size, sp, space);
- BOOST_ASSERT( nullptr != sp);
- // calculate remaining size
- const std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
-#endif
- // create fast-context
- const fcontext_t fctx = make_fcontext( sp, size, & context_entry< Record >);
- BOOST_ASSERT( nullptr != fctx);
- // placment new for control structure on context-stack
- auto rec = ::new ( sp) Record{
- sctx, salloc, std::forward< Fn >( fn) };
- // transfer control structure to context-stack
- return jump_fcontext( fctx, rec).fctx;
-}
-
-template< typename Record, typename StackAlloc, typename Fn >
-fcontext_t context_create( preallocated palloc, StackAlloc salloc, Fn && fn) {
- // reserve space for control structure
-#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
- const std::size_t size = palloc.size - sizeof( Record);
- void * sp = static_cast< char * >( palloc.sp) - sizeof( Record);
-#else
- constexpr std::size_t func_alignment = 64; // alignof( Record);
- constexpr std::size_t func_size = sizeof( Record);
- // reserve space on stack
- void * sp = static_cast< char * >( palloc.sp) - func_size - func_alignment;
- // align sp pointer
- std::size_t space = func_size + func_alignment;
- sp = std::align( func_alignment, func_size, sp, space);
- BOOST_ASSERT( nullptr != sp);
- // calculate remaining size
- const std::size_t size = palloc.size - ( static_cast< char * >( palloc.sp) - static_cast< char * >( sp) );
-#endif
- // create fast-context
- const fcontext_t fctx = make_fcontext( sp, size, & context_entry< Record >);
- BOOST_ASSERT( nullptr != fctx);
- // placment new for control structure on context-stack
- auto rec = ::new ( sp) Record{
- palloc.sctx, salloc, std::forward< Fn >( fn) };
- // transfer control structure to context-stack
- return jump_fcontext( fctx, rec).fctx;
-}
-
-template< typename ... Arg >
-struct result_type {
- typedef std::tuple< Arg ... > type;
-
- static
- type get( detail::transfer_t & t) {
- auto p = static_cast< std::tuple< Arg ... > * >( t.data);
- return std::move( * p);
- }
-};
-
-template< typename Arg >
-struct result_type< Arg > {
- typedef Arg type;
-
- static
- type get( detail::transfer_t & t) {
- auto p = static_cast< std::tuple< Arg > * >( t.data);
- return std::forward< Arg >( std::get< 0 >( * p) );
- }
-};
-
-}
-
-template< typename Ctx, typename Fn, typename ... Arg >
-detail::transfer_t context_ontop( detail::transfer_t t) {
- auto p = static_cast< std::tuple< Fn, std::tuple< Arg ... > > * >( t.data);
- BOOST_ASSERT( nullptr != p);
- typename std::decay< Fn >::type fn = std::forward< Fn >( std::get< 0 >( * p) );
- t.data = & std::get< 1 >( * p);
- Ctx c{ t };
- // execute function, pass continuation via reference
- std::get< 1 >( * p) = detail::helper< sizeof ... (Arg) >::convert( fn( std::move( c) ) );
-#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
- return { detail::exchange( c.t_.fctx, nullptr), & std::get< 1 >( * p) };
-#else
- return { std::exchange( c.t_.fctx, nullptr), & std::get< 1 >( * p) };
-#endif
-}
-
-template< typename Ctx, typename Fn >
-detail::transfer_t context_ontop_void( detail::transfer_t t) {
- auto p = static_cast< std::tuple< Fn > * >( t.data);
- BOOST_ASSERT( nullptr != p);
- typename std::decay< Fn >::type fn = std::forward< Fn >( std::get< 0 >( * p) );
- Ctx c{ t };
- // execute function, pass continuation via reference
- fn( std::move( c) );
-#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
- return { detail::exchange( c.t_.fctx, nullptr), nullptr };
-#else
- return { std::exchange( c.t_.fctx, nullptr), nullptr };
-#endif
-}
-
-class continuation {
-private:
- template< typename Ctx, typename StackAlloc, typename Fn >
- friend class detail::record;
-
- template< typename Ctx, typename Fn, typename ... Arg >
- friend detail::transfer_t
- context_ontop( detail::transfer_t);
-
- template< typename Ctx, typename Fn >
- friend detail::transfer_t
- context_ontop_void( detail::transfer_t);
-
- template< typename StackAlloc, typename Fn, typename ... Arg >
- friend continuation
- callcc( std::allocator_arg_t, StackAlloc, Fn &&, Arg ...);
-
- template< typename StackAlloc, typename Fn, typename ... Arg >
- friend continuation
- callcc( std::allocator_arg_t, preallocated, StackAlloc, Fn &&, Arg ...);
-
- template< typename StackAlloc, typename Fn >
- friend continuation
- callcc( std::allocator_arg_t, StackAlloc, Fn &&);
-
- template< typename StackAlloc, typename Fn >
- friend continuation
- callcc( std::allocator_arg_t, preallocated, StackAlloc, Fn &&);
-
- detail::transfer_t t_{ nullptr, nullptr };
-
- continuation( detail::fcontext_t fctx) noexcept :
- t_{ fctx, nullptr } {
- }
-
- continuation( detail::transfer_t t) noexcept :
- t_{ t.fctx, t.data } {
- }
-
-public:
- continuation() noexcept = default;
-
- ~continuation() {
- if ( nullptr != t_.fctx) {
-#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
- detail::ontop_fcontext( detail::exchange( t_.fctx, nullptr), nullptr, detail::context_unwind);
-#else
- detail::ontop_fcontext( std::exchange( t_.fctx, nullptr), nullptr, detail::context_unwind);
-#endif
- }
- }
-
- continuation( continuation && other) noexcept :
- t_{ other.t_.fctx, other.t_.data } {
- other.t_ = { nullptr, nullptr };
- }
-
- continuation & operator=( continuation && other) noexcept {
- if ( this != & other) {
- continuation tmp = std::move( other);
- swap( tmp);
- }
- return * this;
- }
-
- continuation( continuation const& other) noexcept = delete;
- continuation & operator=( continuation const& other) noexcept = delete;
-
- template< typename ... Arg >
- continuation resume( Arg ... arg) {
- BOOST_ASSERT( nullptr != t_.fctx);
- auto tpl = std::make_tuple( std::forward< Arg >( arg) ... );
- return detail::jump_fcontext(
-#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
- detail::exchange( t_.fctx, nullptr),
-#else
- std::exchange( t_.fctx, nullptr),
-#endif
- & tpl);
- }
-
- template< typename Fn, typename ... Arg >
- continuation resume_with( Fn && fn, Arg ... arg) {
- BOOST_ASSERT( nullptr != t_.fctx);
- auto tpl = std::make_tuple( std::forward< Fn >( fn), std::forward< Arg >( arg) ... );
- return detail::ontop_fcontext(
-#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
- detail::exchange( t_.fctx, nullptr),
-#else
- std::exchange( t_.fctx, nullptr),
-#endif
- & tpl,
- context_ontop< continuation, Fn, Arg ... >);
- }
-
- continuation resume() {
- BOOST_ASSERT( nullptr != t_.fctx);
- return detail::jump_fcontext(
-#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
- detail::exchange( t_.fctx, nullptr),
-#else
- std::exchange( t_.fctx, nullptr),
-#endif
- nullptr);
- }
-
- template< typename Fn >
- continuation resume_with( Fn && fn) {
- BOOST_ASSERT( nullptr != t_.fctx);
- auto p = std::make_tuple( std::forward< Fn >( fn) );
- return detail::ontop_fcontext(
-#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
- detail::exchange( t_.fctx, nullptr),
-#else
- std::exchange( t_.fctx, nullptr),
-#endif
- & p,
- context_ontop_void< continuation, Fn >);
- }
-
- bool data_available() noexcept {
- return * this && nullptr != t_.data;
- }
-
- template< typename ... Arg >
- typename detail::result_type< Arg ... >::type get_data() {
- BOOST_ASSERT( nullptr != t_.data);
- return detail::result_type< Arg ... >::get( t_);
- }
-
- explicit operator bool() const noexcept {
- return nullptr != t_.fctx;
- }
-
- bool operator!() const noexcept {
- return nullptr == t_.fctx;
- }
-
- bool operator==( continuation const& other) const noexcept {
- return t_.fctx == other.t_.fctx;
- }
-
- bool operator!=( continuation const& other) const noexcept {
- return t_.fctx != other.t_.fctx;
- }
-
- bool operator<( continuation const& other) const noexcept {
- return t_.fctx < other.t_.fctx;
- }
-
- bool operator>( continuation const& other) const noexcept {
- return other.t_.fctx < t_.fctx;
- }
-
- bool operator<=( continuation const& other) const noexcept {
- return ! ( * this > other);
- }
-
- bool operator>=( continuation const& other) const noexcept {
- return ! ( * this < other);
- }
-
- template< typename charT, class traitsT >
- friend std::basic_ostream< charT, traitsT > &
- operator<<( std::basic_ostream< charT, traitsT > & os, continuation const& other) {
- if ( nullptr != other.t_.fctx) {
- return os << other.t_.fctx;
- } else {
- return os << "{not-a-context}";
- }
- }
-
- void swap( continuation & other) noexcept {
- std::swap( t_, other.t_);
- }
-};
-
-// Arg
-template<
- typename Fn,
- typename ... Arg,
- typename = detail::disable_overload< continuation, Fn >
->
-continuation
-callcc( Fn && fn, Arg ... arg) {
- return callcc(
- std::allocator_arg, fixedsize_stack(),
- std::forward< Fn >( fn), std::forward< Arg >( arg) ...);
-}
-
-template<
- typename StackAlloc,
- typename Fn,
- typename ... Arg
->
-continuation
-callcc( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Arg ... arg) {
- using Record = detail::record< continuation, StackAlloc, Fn >;
- return continuation{
- detail::context_create< Record >(
- salloc, std::forward< Fn >( fn) ) }.resume(
- std::forward< Arg >( arg) ... );
-}
-
-template<
- typename StackAlloc,
- typename Fn,
- typename ... Arg
->
-continuation
-callcc( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Arg ... arg) {
- using Record = detail::record< continuation, StackAlloc, Fn >;
- return continuation{
- detail::context_create< Record >(
- palloc, salloc, std::forward< Fn >( fn) ) }.resume(
- std::forward< Arg >( arg) ... );
-}
-
-// void
-template<
- typename Fn,
- typename = detail::disable_overload< continuation, Fn >
->
-continuation
-callcc( Fn && fn) {
- return callcc(
- std::allocator_arg, fixedsize_stack(),
- std::forward< Fn >( fn) );
-}
-
-template< typename StackAlloc, typename Fn >
-continuation
-callcc( std::allocator_arg_t, StackAlloc salloc, Fn && fn) {
- using Record = detail::record< continuation, StackAlloc, Fn >;
- return continuation{
- detail::context_create< Record >(
- salloc, std::forward< Fn >( fn) ) }.resume();
-}
-
-template< typename StackAlloc, typename Fn >
-continuation
-callcc( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn) {
- using Record = detail::record< continuation, StackAlloc, Fn >;
- return continuation{
- detail::context_create< Record >(
- palloc, salloc, std::forward< Fn >( fn) ) }.resume();
-}
-
-#if defined(BOOST_USE_SEGMENTED_STACKS)
-template<
- typename Fn,
- typename ... Arg
->
-continuation
-callcc( std::allocator_arg_t, segmented_stack, Fn &&, Arg ...);
-
-template<
- typename StackAlloc,
- typename Fn,
- typename ... Arg
->
-continuation
-callcc( std::allocator_arg_t, preallocated, segmented_stack, Fn &&, Arg ...);
-#endif
-
-// swap
-inline
-void swap( continuation & l, continuation & r) noexcept {
- l.swap( r);
-}
-
-}}
-
-#if defined(BOOST_MSVC)
-# pragma warning(pop)
-#endif
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXT_CONTINUATION_H
diff --git a/boost/context/continuation_fcontext.hpp b/boost/context/continuation_fcontext.hpp
new file mode 100644
index 0000000000..5c309c3fed
--- /dev/null
+++ b/boost/context/continuation_fcontext.hpp
@@ -0,0 +1,382 @@
+
+// Copyright Oliver Kowalke 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_CONTEXT_CONTINUATION_H
+#define BOOST_CONTEXT_CONTINUATION_H
+
+#include <boost/context/detail/config.hpp>
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <exception>
+#include <functional>
+#include <memory>
+#include <ostream>
+#include <tuple>
+#include <utility>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/intrusive_ptr.hpp>
+
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+#include <boost/context/detail/exchange.hpp>
+#endif
+#if defined(BOOST_NO_CXX17_STD_INVOKE)
+#include <boost/context/detail/invoke.hpp>
+#endif
+#include <boost/context/detail/disable_overload.hpp>
+#include <boost/context/detail/exception.hpp>
+#include <boost/context/detail/fcontext.hpp>
+#include <boost/context/detail/tuple.hpp>
+#include <boost/context/fixedsize_stack.hpp>
+#include <boost/context/flags.hpp>
+#include <boost/context/preallocated.hpp>
+#include <boost/context/segmented_stack.hpp>
+#include <boost/context/stack_context.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+#if defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable: 4702)
+#endif
+
+namespace boost {
+namespace context {
+namespace detail {
+
+inline
+transfer_t context_unwind( transfer_t t) {
+ throw forced_unwind( t.fctx);
+ return { nullptr, nullptr };
+}
+
+template< typename Rec >
+transfer_t context_exit( transfer_t t) noexcept {
+ Rec * rec = static_cast< Rec * >( t.data);
+ // destroy context stack
+ rec->deallocate();
+ return { nullptr, nullptr };
+}
+
+template< typename Rec >
+void context_entry( transfer_t t) noexcept {
+ // transfer control structure to the context-stack
+ Rec * rec = static_cast< Rec * >( t.data);
+ BOOST_ASSERT( nullptr != t.fctx);
+ BOOST_ASSERT( nullptr != rec);
+ try {
+ // jump back to `create_context()`
+ t = jump_fcontext( t.fctx, nullptr);
+ // start executing
+ t.fctx = rec->run( t.fctx);
+ } catch ( forced_unwind const& e) {
+ t = { e.fctx, nullptr };
+ }
+ BOOST_ASSERT( nullptr != t.fctx);
+ // destroy context-stack of `this`context on next context
+ ontop_fcontext( t.fctx, rec, context_exit< Rec >);
+ BOOST_ASSERT_MSG( false, "context already terminated");
+}
+
+template< typename Ctx, typename Fn >
+transfer_t context_ontop( transfer_t t) {
+ auto p = static_cast< std::tuple< Fn > * >( t.data);
+ BOOST_ASSERT( nullptr != p);
+ typename std::decay< Fn >::type fn = std::get< 0 >( * p);
+ t.data = nullptr;
+ Ctx c{ t.fctx };
+ // execute function, pass continuation via reference
+ fn( std::move( c) );
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ return { exchange( c.fctx_, nullptr), nullptr };
+#else
+ return { std::exchange( c.fctx_, nullptr), nullptr };
+#endif
+}
+
+template< typename Ctx, typename StackAlloc, typename Fn >
+class record {
+private:
+ stack_context sctx_;
+ StackAlloc salloc_;
+ typename std::decay< Fn >::type fn_;
+
+ static void destroy( record * p) noexcept {
+ StackAlloc salloc = p->salloc_;
+ stack_context sctx = p->sctx_;
+ // deallocate record
+ p->~record();
+ // destroy stack with stack allocator
+ salloc.deallocate( sctx);
+ }
+
+public:
+ record( stack_context sctx, StackAlloc const& salloc,
+ Fn && fn) noexcept :
+ sctx_( sctx),
+ salloc_( salloc),
+ fn_( std::forward< Fn >( fn) ) {
+ }
+
+ record( record const&) = delete;
+ record & operator=( record const&) = delete;
+
+ void deallocate() noexcept {
+ destroy( this);
+ }
+
+ fcontext_t run( fcontext_t fctx) {
+ Ctx c{ fctx };
+ // invoke context-function
+#if defined(BOOST_NO_CXX17_STD_INVOKE)
+ c = invoke( fn_, std::move( c) );
+#else
+ c = std::invoke( fn_, std::move( c) );
+#endif
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ return exchange( c.fctx_, nullptr);
+#else
+ return std::exchange( c.fctx_, nullptr);
+#endif
+ }
+};
+
+template< typename Record, typename StackAlloc, typename Fn >
+fcontext_t create_context1( StackAlloc salloc, Fn && fn) {
+ auto sctx = salloc.allocate();
+ // reserve space for control structure
+ void * storage = reinterpret_cast< void * >(
+ ( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sizeof( Record) ) )
+ & ~static_cast< uintptr_t >( 0xff) );
+ // placment new for control structure on context stack
+ Record * record = new ( storage) Record{
+ sctx, salloc, std::forward< Fn >( fn) };
+ // 64byte gab between control structure and stack top
+ // should be 16byte aligned
+ void * stack_top = reinterpret_cast< void * >(
+ reinterpret_cast< uintptr_t >( storage) - static_cast< uintptr_t >( 64) );
+ void * stack_bottom = reinterpret_cast< void * >(
+ reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sctx.size) );
+ // create fast-context
+ const std::size_t size = reinterpret_cast< uintptr_t >( stack_top) - reinterpret_cast< uintptr_t >( stack_bottom);
+ const fcontext_t fctx = make_fcontext( stack_top, size, & context_entry< Record >);
+ BOOST_ASSERT( nullptr != fctx);
+ // transfer control structure to context-stack
+ return jump_fcontext( fctx, record).fctx;
+}
+
+template< typename Record, typename StackAlloc, typename Fn >
+fcontext_t create_context2( preallocated palloc, StackAlloc salloc, Fn && fn) {
+ // reserve space for control structure
+ void * storage = reinterpret_cast< void * >(
+ ( reinterpret_cast< uintptr_t >( palloc.sp) - static_cast< uintptr_t >( sizeof( Record) ) )
+ & ~ static_cast< uintptr_t >( 0xff) );
+ // placment new for control structure on context-stack
+ Record * record = new ( storage) Record{
+ palloc.sctx, salloc, std::forward< Fn >( fn) };
+ // 64byte gab between control structure and stack top
+ void * stack_top = reinterpret_cast< void * >(
+ reinterpret_cast< uintptr_t >( storage) - static_cast< uintptr_t >( 64) );
+ void * stack_bottom = reinterpret_cast< void * >(
+ reinterpret_cast< uintptr_t >( palloc.sctx.sp) - static_cast< uintptr_t >( palloc.sctx.size) );
+ // create fast-context
+ const std::size_t size = reinterpret_cast< uintptr_t >( stack_top) - reinterpret_cast< uintptr_t >( stack_bottom);
+ const fcontext_t fctx = make_fcontext( stack_top, size, & context_entry< Record >);
+ BOOST_ASSERT( nullptr != fctx);
+ // transfer control structure to context-stack
+ return jump_fcontext( fctx, record).fctx;
+}
+
+}
+
+class continuation {
+private:
+ template< typename Ctx, typename StackAlloc, typename Fn >
+ friend class detail::record;
+
+ template< typename Ctx, typename Fn >
+ friend detail::transfer_t
+ detail::context_ontop( detail::transfer_t);
+
+ template< typename StackAlloc, typename Fn >
+ friend continuation
+ callcc( std::allocator_arg_t, StackAlloc, Fn &&);
+
+ template< typename StackAlloc, typename Fn >
+ friend continuation
+ callcc( std::allocator_arg_t, preallocated, StackAlloc, Fn &&);
+
+ detail::fcontext_t fctx_{ nullptr };
+
+ continuation( detail::fcontext_t fctx) noexcept :
+ fctx_{ fctx } {
+ }
+
+public:
+ continuation() noexcept = default;
+
+ ~continuation() {
+ if ( BOOST_UNLIKELY( nullptr != fctx_) ) {
+ detail::ontop_fcontext(
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ detail::exchange( fctx_, nullptr),
+#else
+ std::exchange( fctx_, nullptr),
+#endif
+ nullptr,
+ detail::context_unwind);
+ }
+ }
+
+ continuation( continuation && other) noexcept {
+ std::swap( fctx_, other.fctx_);
+ }
+
+ continuation & operator=( continuation && other) noexcept {
+ if ( BOOST_LIKELY( this != & other) ) {
+ continuation tmp = std::move( other);
+ swap( tmp);
+ }
+ return * this;
+ }
+
+ continuation( continuation const& other) noexcept = delete;
+ continuation & operator=( continuation const& other) noexcept = delete;
+
+ continuation resume() {
+ BOOST_ASSERT( nullptr != fctx_);
+ return detail::jump_fcontext(
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ detail::exchange( fctx_, nullptr),
+#else
+ std::exchange( fctx_, nullptr),
+#endif
+ nullptr).fctx;
+ }
+
+ template< typename Fn >
+ continuation resume_with( Fn && fn) {
+ BOOST_ASSERT( nullptr != fctx_);
+ auto p = std::make_tuple( std::forward< Fn >( fn) );
+ return detail::ontop_fcontext(
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ detail::exchange( fctx_, nullptr),
+#else
+ std::exchange( fctx_, nullptr),
+#endif
+ & p,
+ detail::context_ontop< continuation, Fn >).fctx;
+ }
+
+ explicit operator bool() const noexcept {
+ return nullptr != fctx_;
+ }
+
+ bool operator!() const noexcept {
+ return nullptr == fctx_;
+ }
+
+ bool operator==( continuation const& other) const noexcept {
+ return fctx_ == other.fctx_;
+ }
+
+ bool operator!=( continuation const& other) const noexcept {
+ return fctx_ != other.fctx_;
+ }
+
+ bool operator<( continuation const& other) const noexcept {
+ return fctx_ < other.fctx_;
+ }
+
+ bool operator>( continuation const& other) const noexcept {
+ return other.fctx_ < fctx_;
+ }
+
+ bool operator<=( continuation const& other) const noexcept {
+ return ! ( * this > other);
+ }
+
+ bool operator>=( continuation const& other) const noexcept {
+ return ! ( * this < other);
+ }
+
+ template< typename charT, class traitsT >
+ friend std::basic_ostream< charT, traitsT > &
+ operator<<( std::basic_ostream< charT, traitsT > & os, continuation const& other) {
+ if ( nullptr != other.fctx_) {
+ return os << other.fctx_;
+ } else {
+ return os << "{not-a-context}";
+ }
+ }
+
+ void swap( continuation & other) noexcept {
+ std::swap( fctx_, other.fctx_);
+ }
+};
+
+template<
+ typename Fn,
+ typename = detail::disable_overload< continuation, Fn >
+>
+continuation
+callcc( Fn && fn) {
+ return callcc(
+ std::allocator_arg, fixedsize_stack(),
+ std::forward< Fn >( fn) );
+}
+
+template< typename StackAlloc, typename Fn >
+continuation
+callcc( std::allocator_arg_t, StackAlloc salloc, Fn && fn) {
+ using Record = detail::record< continuation, StackAlloc, Fn >;
+ return continuation{
+ detail::create_context1< Record >(
+ salloc, std::forward< Fn >( fn) ) }.resume();
+}
+
+template< typename StackAlloc, typename Fn >
+continuation
+callcc( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn) {
+ using Record = detail::record< continuation, StackAlloc, Fn >;
+ return continuation{
+ detail::create_context2< Record >(
+ palloc, salloc, std::forward< Fn >( fn) ) }.resume();
+}
+
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+template< typename Fn >
+continuation
+callcc( std::allocator_arg_t, segmented_stack, Fn &&);
+
+template< typename StackAlloc, typename Fn >
+continuation
+callcc( std::allocator_arg_t, preallocated, segmented_stack, Fn &&);
+#endif
+
+// swap
+inline
+void swap( continuation & l, continuation & r) noexcept {
+ l.swap( r);
+}
+
+}}
+
+#if defined(BOOST_MSVC)
+# pragma warning(pop)
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_CONTINUATION_H
diff --git a/boost/context/continuation_ucontext.hpp b/boost/context/continuation_ucontext.hpp
new file mode 100644
index 0000000000..6f964dc6f6
--- /dev/null
+++ b/boost/context/continuation_ucontext.hpp
@@ -0,0 +1,525 @@
+
+// Copyright Oliver Kowalke 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_CONTEXT_CONTINUATION_H
+#define BOOST_CONTEXT_CONTINUATION_H
+
+#include <boost/predef.h>
+#if BOOST_OS_MACOS
+#define _XOPEN_SOURCE 600
+#endif
+
+extern "C" {
+#include <ucontext.h>
+}
+
+#include <boost/context/detail/config.hpp>
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <functional>
+#include <memory>
+#include <ostream>
+#include <system_error>
+#include <tuple>
+#include <utility>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+#include <boost/context/detail/disable_overload.hpp>
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+#include <boost/context/detail/exchange.hpp>
+#endif
+#if defined(BOOST_NO_CXX17_STD_INVOKE)
+#include <boost/context/detail/invoke.hpp>
+#endif
+#include <boost/context/fixedsize_stack.hpp>
+#include <boost/context/flags.hpp>
+#include <boost/context/preallocated.hpp>
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+#include <boost/context/segmented_stack.hpp>
+#endif
+#include <boost/context/stack_context.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+#if defined(BOOST_USE_ASAN)
+extern "C" {
+void __sanitizer_start_switch_fiber( void **, const void *, size_t);
+void __sanitizer_finish_switch_fiber( void *, const void **, size_t *);
+}
+#endif
+
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+extern "C" {
+void __splitstack_getcontext( void * [BOOST_CONTEXT_SEGMENTS]);
+void __splitstack_setcontext( void * [BOOST_CONTEXT_SEGMENTS]);
+}
+#endif
+
+namespace boost {
+namespace context {
+namespace detail {
+
+// tampoline function
+// entered if the execution context
+// is resumed for the first time
+template< typename Record >
+static void entry_func( void * data) noexcept {
+ Record * record = static_cast< Record * >( data);
+ BOOST_ASSERT( nullptr != record);
+ // start execution of toplevel context-function
+ record->run();
+}
+
+struct BOOST_CONTEXT_DECL activation_record {
+ thread_local static activation_record * current_rec;
+
+ ucontext_t uctx{};
+ stack_context sctx{};
+ bool main_ctx{ true };
+ activation_record * from{ nullptr };
+ std::function< void(activation_record*&) > ontop{};
+ bool terminated{ false };
+ bool force_unwind{ false };
+#if defined(BOOST_USE_ASAN)
+ void * fake_stack{ nullptr };
+ void * stack_bottom{ nullptr };
+ std::size_t stack_size{ 0 };
+ bool started{ false };
+#endif
+
+ static activation_record *& current() noexcept;
+
+ // used for toplevel-context
+ // (e.g. main context, thread-entry context)
+ activation_record() {
+ if ( BOOST_UNLIKELY( 0 != ::getcontext( & uctx) ) ) {
+ throw std::system_error(
+ std::error_code( errno, std::system_category() ),
+ "getcontext() failed");
+ }
+#if defined(BOOST_USE_ASAN)
+ stack_bottom = uctx.uc_stack.ss_sp;
+ stack_size = uctx.uc_stack.ss_size;
+#endif
+ }
+
+ activation_record( stack_context sctx_) noexcept :
+ sctx( sctx_ ),
+ main_ctx( false ) {
+ }
+
+ virtual ~activation_record() {
+ }
+
+ activation_record( activation_record const&) = delete;
+ activation_record & operator=( activation_record const&) = delete;
+
+ bool is_main_context() const noexcept {
+ return main_ctx;
+ }
+
+ activation_record * resume() {
+ from = current();
+ // store `this` in static, thread local pointer
+ // `this` will become the active (running) context
+ current() = this;
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+ // adjust segmented stack properties
+ __splitstack_getcontext( from->sctx.segments_ctx);
+ __splitstack_setcontext( sctx.segments_ctx);
+#endif
+#if defined(BOOST_USE_ASAN)
+ if ( from->started) {
+ __sanitizer_finish_switch_fiber( from->fake_stack, (const void **) & from->stack_bottom,
+ & from->stack_size);
+ from->started = false;
+ }
+ __sanitizer_start_switch_fiber( & fake_stack, stack_bottom, stack_size);
+ started = true;
+#endif
+ // context switch from parent context to `this`-context
+ ::swapcontext( & from->uctx, & uctx);
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ return exchange( current()->from, nullptr);
+#else
+ return std::exchange( current()->from, nullptr);
+#endif
+ }
+
+ template< typename Ctx, typename Fn >
+ activation_record * resume_with( Fn && fn) {
+ from = current();
+ // store `this` in static, thread local pointer
+ // `this` will become the active (running) context
+ // returned by continuation::current()
+ current() = this;
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ current()->ontop = std::bind(
+ [](typename std::decay< Fn >::type & fn, activation_record *& ptr){
+ Ctx c{ ptr };
+ fn( std::move( c) );
+ if ( ! c) {
+ ptr = nullptr;
+ }
+ },
+ std::forward< Fn >( fn),
+ std::placeholders::_1);
+#else
+ current()->ontop = [fn=std::forward<Fn>(fn)](activation_record *& ptr){
+ Ctx c{ ptr };
+ fn( std::move( c) );
+ if ( ! c) {
+ ptr = nullptr;
+ }
+ };
+#endif
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+ // adjust segmented stack properties
+ __splitstack_getcontext( from->sctx.segments_ctx);
+ __splitstack_setcontext( sctx.segments_ctx);
+#endif
+#if defined(BOOST_USE_ASAN)
+ if ( from->started) {
+ __sanitizer_finish_switch_fiber( from->fake_stack, (const void **) & from->stack_bottom,
+ & from->stack_size);
+ from->started = false;
+ }
+ __sanitizer_start_switch_fiber( & fake_stack, stack_bottom, stack_size);
+ started = true;
+#endif
+ // context switch from parent context to `this`-context
+ ::swapcontext( & from->uctx, & uctx);
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ return exchange( current()->from, nullptr);
+#else
+ return std::exchange( current()->from, nullptr);
+#endif
+ }
+
+ virtual void deallocate() noexcept {
+ }
+};
+
+struct BOOST_CONTEXT_DECL activation_record_initializer {
+ activation_record_initializer() noexcept;
+ ~activation_record_initializer();
+};
+
+struct forced_unwind {
+ activation_record * from{ nullptr };
+
+ forced_unwind( activation_record * from_) noexcept :
+ from{ from_ } {
+ }
+};
+
+template< typename Ctx, typename StackAlloc, typename Fn >
+class capture_record : public activation_record {
+private:
+ StackAlloc salloc_;
+ typename std::decay< Fn >::type fn_;
+
+ static void destroy( capture_record * p) noexcept {
+ StackAlloc salloc = p->salloc_;
+ stack_context sctx = p->sctx;
+ // deallocate activation record
+ p->~capture_record();
+ // destroy stack with stack allocator
+ salloc.deallocate( sctx);
+ }
+
+public:
+ capture_record( stack_context sctx, StackAlloc const& salloc, Fn && fn) noexcept :
+ activation_record{ sctx },
+ salloc_{ salloc },
+ fn_( std::forward< Fn >( fn) ) {
+ }
+
+ void deallocate() noexcept override final {
+ BOOST_ASSERT( main_ctx || ( ! main_ctx && terminated) );
+ destroy( this);
+ }
+
+ void run() {
+ Ctx c{ from };
+ try {
+ // invoke context-function
+#if defined(BOOST_NO_CXX17_STD_APPLY)
+ c = invoke( fn_, std::move( c) );
+#else
+ c = std::invoke( fn_, std::move( c) );
+#endif
+ } catch ( forced_unwind const& ex) {
+ c = Ctx{ ex.from };
+ }
+ // this context has finished its task
+ from = nullptr;
+ ontop = nullptr;
+ terminated = true;
+ force_unwind = false;
+ c.resume();
+ BOOST_ASSERT_MSG( false, "continuation already terminated");
+ }
+};
+
+template< typename Ctx, typename StackAlloc, typename Fn >
+static activation_record * create_context1( StackAlloc salloc, Fn && fn) {
+ typedef capture_record< Ctx, StackAlloc, Fn > capture_t;
+
+ auto sctx = salloc.allocate();
+ // reserve space for control structure
+ void * storage = reinterpret_cast< void * >(
+ ( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) )
+ & ~ static_cast< uintptr_t >( 0xff) );
+ // placment new for control structure on context stack
+ capture_t * record = new ( storage) capture_t{
+ sctx, salloc, std::forward< Fn >( fn) };
+ // stack bottom
+ void * stack_bottom = reinterpret_cast< void * >(
+ reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sctx.size) );
+ // create user-context
+ if ( BOOST_UNLIKELY( 0 != ::getcontext( & record->uctx) ) ) {
+ throw std::system_error(
+ std::error_code( errno, std::system_category() ),
+ "getcontext() failed");
+ }
+ record->uctx.uc_stack.ss_sp = stack_bottom;
+ // 64byte gap between control structure and stack top
+ record->uctx.uc_stack.ss_size = reinterpret_cast< uintptr_t >( storage) -
+ reinterpret_cast< uintptr_t >( stack_bottom) - static_cast< uintptr_t >( 64);
+ record->uctx.uc_link = nullptr;
+ ::makecontext( & record->uctx, ( void (*)() ) & entry_func< capture_t >, 1, record);
+#if defined(BOOST_USE_ASAN)
+ record->stack_bottom = record->uctx.uc_stack.ss_sp;
+ record->stack_size = record->uctx.uc_stack.ss_size;
+#endif
+ return record;
+}
+
+template< typename Ctx, typename StackAlloc, typename Fn >
+static activation_record * create_context2( preallocated palloc, StackAlloc salloc, Fn && fn) {
+ typedef capture_record< Ctx, StackAlloc, Fn > capture_t;
+
+ // reserve space for control structure
+ void * storage = reinterpret_cast< void * >(
+ ( reinterpret_cast< uintptr_t >( palloc.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) )
+ & ~ static_cast< uintptr_t >( 0xff) );
+ // placment new for control structure on context stack
+ capture_t * record = new ( storage) capture_t{
+ palloc.sctx, salloc, std::forward< Fn >( fn) };
+ // stack bottom
+ void * stack_bottom = reinterpret_cast< void * >(
+ reinterpret_cast< uintptr_t >( palloc.sctx.sp) - static_cast< uintptr_t >( palloc.sctx.size) );
+ // create user-context
+ if ( BOOST_UNLIKELY( 0 != ::getcontext( & record->uctx) ) ) {
+ throw std::system_error(
+ std::error_code( errno, std::system_category() ),
+ "getcontext() failed");
+ }
+ record->uctx.uc_stack.ss_sp = stack_bottom;
+ // 64byte gap between control structure and stack top
+ record->uctx.uc_stack.ss_size = reinterpret_cast< uintptr_t >( storage) -
+ reinterpret_cast< uintptr_t >( stack_bottom) - static_cast< uintptr_t >( 64);
+ record->uctx.uc_link = nullptr;
+ ::makecontext( & record->uctx, ( void (*)() ) & entry_func< capture_t >, 1, record);
+#if defined(BOOST_USE_ASAN)
+ record->stack_bottom = record->uctx.uc_stack.ss_sp;
+ record->stack_size = record->uctx.uc_stack.ss_size;
+#endif
+ return record;
+}
+
+}
+
+class BOOST_CONTEXT_DECL continuation {
+private:
+ friend struct detail::activation_record;
+
+ template< typename Ctx, typename StackAlloc, typename Fn >
+ friend class detail::capture_record;
+
+ template< typename Ctx, typename StackAlloc, typename Fn >
+ friend detail::activation_record * detail::create_context1( StackAlloc, Fn &&);
+
+ template< typename Ctx, typename StackAlloc, typename Fn >
+ friend detail::activation_record * detail::create_context2( preallocated, StackAlloc, Fn &&);
+
+ template< typename StackAlloc, typename Fn >
+ friend continuation
+ callcc( std::allocator_arg_t, StackAlloc, Fn &&);
+
+ template< typename StackAlloc, typename Fn >
+ friend continuation
+ callcc( std::allocator_arg_t, preallocated, StackAlloc, Fn &&);
+
+ detail::activation_record * ptr_{ nullptr };
+
+ continuation( detail::activation_record * ptr) noexcept :
+ ptr_{ ptr } {
+ }
+
+public:
+ continuation() = default;
+
+ ~continuation() {
+ if ( BOOST_UNLIKELY( nullptr != ptr_) && ! ptr_->main_ctx) {
+ if ( BOOST_LIKELY( ! ptr_->terminated) ) {
+ ptr_->force_unwind = true;
+ ptr_->resume();
+ BOOST_ASSERT( ptr_->terminated);
+ }
+ ptr_->deallocate();
+ }
+ }
+
+ continuation( continuation const&) = delete;
+ continuation & operator=( continuation const&) = delete;
+
+ continuation( continuation && other) noexcept :
+ ptr_{ nullptr } {
+ swap( other);
+ }
+
+ continuation & operator=( continuation && other) noexcept {
+ if ( BOOST_LIKELY( this != & other) ) {
+ ptr_ = other.ptr_;
+ other.ptr_ = nullptr;
+ }
+ return * this;
+ }
+
+ continuation resume() {
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ detail::activation_record * ptr = detail::exchange( ptr_, nullptr)->resume();
+#else
+ detail::activation_record * ptr = std::exchange( ptr_, nullptr)->resume();
+#endif
+ if ( BOOST_UNLIKELY( detail::activation_record::current()->force_unwind) ) {
+ throw detail::forced_unwind{ ptr};
+ } else if ( BOOST_UNLIKELY( nullptr != detail::activation_record::current()->ontop) ) {
+ detail::activation_record::current()->ontop( ptr);
+ detail::activation_record::current()->ontop = nullptr;
+ }
+ return continuation{ ptr };
+ }
+
+ template< typename Fn >
+ continuation resume_with( Fn && fn) {
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ detail::activation_record * ptr =
+ detail::exchange( ptr_, nullptr)->resume_with< continuation >( std::forward< Fn >( fn) );
+#else
+ detail::activation_record * ptr =
+ std::exchange( ptr_, nullptr)->resume_with< continuation >( std::forward< Fn >( fn) );
+#endif
+ if ( BOOST_UNLIKELY( detail::activation_record::current()->force_unwind) ) {
+ throw detail::forced_unwind{ ptr};
+ } else if ( BOOST_UNLIKELY( nullptr != detail::activation_record::current()->ontop) ) {
+ detail::activation_record::current()->ontop( ptr);
+ detail::activation_record::current()->ontop = nullptr;
+ }
+ return continuation{ ptr };
+ }
+
+ explicit operator bool() const noexcept {
+ return nullptr != ptr_ && ! ptr_->terminated;
+ }
+
+ bool operator!() const noexcept {
+ return nullptr == ptr_ || ptr_->terminated;
+ }
+
+ bool operator==( continuation const& other) const noexcept {
+ return ptr_ == other.ptr_;
+ }
+
+ bool operator!=( continuation const& other) const noexcept {
+ return ptr_ != other.ptr_;
+ }
+
+ bool operator<( continuation const& other) const noexcept {
+ return ptr_ < other.ptr_;
+ }
+
+ bool operator>( continuation const& other) const noexcept {
+ return other.ptr_ < ptr_;
+ }
+
+ bool operator<=( continuation const& other) const noexcept {
+ return ! ( * this > other);
+ }
+
+ bool operator>=( continuation const& other) const noexcept {
+ return ! ( * this < other);
+ }
+
+ template< typename charT, class traitsT >
+ friend std::basic_ostream< charT, traitsT > &
+ operator<<( std::basic_ostream< charT, traitsT > & os, continuation const& other) {
+ if ( nullptr != other.ptr_) {
+ return os << other.ptr_;
+ } else {
+ return os << "{not-a-context}";
+ }
+ }
+
+ void swap( continuation & other) noexcept {
+ std::swap( ptr_, other.ptr_);
+ }
+};
+
+template<
+ typename Fn,
+ typename = detail::disable_overload< continuation, Fn >
+>
+continuation
+callcc( Fn && fn) {
+ return callcc(
+ std::allocator_arg,
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+ segmented_stack(),
+#else
+ fixedsize_stack(),
+#endif
+ std::forward< Fn >( fn) );
+}
+
+template< typename StackAlloc, typename Fn >
+continuation
+callcc( std::allocator_arg_t, StackAlloc salloc, Fn && fn) {
+ return continuation{
+ detail::create_context1< continuation >(
+ salloc, std::forward< Fn >( fn) ) }.resume();
+}
+
+template< typename StackAlloc, typename Fn >
+continuation
+callcc( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn) {
+ return continuation{
+ detail::create_context2< continuation >(
+ palloc, salloc, std::forward< Fn >( fn) ) }.resume();
+}
+
+inline
+void swap( continuation & l, continuation & r) noexcept {
+ l.swap( r);
+}
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_CONTINUATION_H
diff --git a/boost/context/continuation_winfib.hpp b/boost/context/continuation_winfib.hpp
new file mode 100644
index 0000000000..8a814b0bd8
--- /dev/null
+++ b/boost/context/continuation_winfib.hpp
@@ -0,0 +1,453 @@
+
+// Copyright Oliver Kowalke 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_CONTEXT_CONTINUATION_H
+#define BOOST_CONTEXT_CONTINUATION_H
+
+#include <windows.h>
+
+#include <boost/context/detail/config.hpp>
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <functional>
+#include <memory>
+#include <ostream>
+#include <system_error>
+#include <tuple>
+#include <utility>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+#include <boost/context/detail/disable_overload.hpp>
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+#include <boost/context/detail/exchange.hpp>
+#endif
+#if defined(BOOST_NO_CXX17_STD_INVOKE)
+#include <boost/context/detail/invoke.hpp>
+#endif
+#include <boost/context/fixedsize_stack.hpp>
+#include <boost/context/flags.hpp>
+#include <boost/context/preallocated.hpp>
+#include <boost/context/stack_context.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+#if defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable: 4702)
+#endif
+
+namespace boost {
+namespace context {
+namespace detail {
+
+// tampoline function
+// entered if the execution context
+// is resumed for the first time
+template< typename Record >
+static VOID WINAPI entry_func( LPVOID data) noexcept {
+ Record * record = static_cast< Record * >( data);
+ BOOST_ASSERT( nullptr != record);
+ // start execution of toplevel context-function
+ record->run();
+}
+
+struct BOOST_CONTEXT_DECL activation_record {
+ thread_local static activation_record * current_rec;
+
+ LPVOID fiber{ nullptr };
+ stack_context sctx{};
+ bool main_ctx{ true };
+ activation_record * from{ nullptr };
+ std::function< void(activation_record*&) > ontop{};
+ bool terminated{ false };
+ bool force_unwind{ false };
+
+ static activation_record *& current() noexcept;
+
+ // used for toplevel-context
+ // (e.g. main context, thread-entry context)
+ activation_record() noexcept {
+#if ( _WIN32_WINNT > 0x0600)
+ if ( ::IsThreadAFiber() ) {
+ fiber = ::GetCurrentFiber();
+ } else {
+ fiber = ::ConvertThreadToFiber( nullptr);
+ }
+#else
+ fiber = ::ConvertThreadToFiber( nullptr);
+ if ( BOOST_UNLIKELY( nullptr == fiber) ) {
+ DWORD err = ::GetLastError();
+ BOOST_ASSERT( ERROR_ALREADY_FIBER == err);
+ fiber = ::GetCurrentFiber();
+ BOOST_ASSERT( nullptr != fiber);
+ BOOST_ASSERT( reinterpret_cast< LPVOID >( 0x1E00) != fiber);
+ }
+#endif
+ }
+
+ activation_record( stack_context sctx_) noexcept :
+ sctx{ sctx_ },
+ main_ctx{ false } {
+ }
+
+ virtual ~activation_record() {
+ if ( BOOST_UNLIKELY( main_ctx) ) {
+ ::ConvertFiberToThread();
+ } else {
+ ::DeleteFiber( fiber);
+ }
+ }
+
+ activation_record( activation_record const&) = delete;
+ activation_record & operator=( activation_record const&) = delete;
+
+ bool is_main_context() const noexcept {
+ return main_ctx;
+ }
+
+ activation_record * resume() {
+ from = current();
+ // store `this` in static, thread local pointer
+ // `this` will become the active (running) context
+ current() = this;
+ // context switch from parent context to `this`-context
+ // context switch
+ ::SwitchToFiber( fiber);
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ return detail::exchange( current()->from, nullptr);
+#else
+ return std::exchange( current()->from, nullptr);
+#endif
+ }
+
+ template< typename Ctx, typename Fn >
+ activation_record * resume_with( Fn && fn) {
+ from = current();
+ // store `this` in static, thread local pointer
+ // `this` will become the active (running) context
+ // returned by continuation::current()
+ current() = this;
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ current()->ontop = std::bind(
+ [](typename std::decay< Fn >::type & fn, activation_record *& ptr){
+ Ctx c{ ptr };
+ fn( std::move( c) );
+ if ( ! c) {
+ ptr = nullptr;
+ }
+ },
+ std::forward< Fn >( fn),
+ std::placeholders::_1);
+#else
+ current()->ontop = [fn=std::forward<Fn>(fn)](activation_record *& ptr){
+ Ctx c{ ptr };
+ fn( std::move( c) );
+ if ( ! c) {
+ ptr = nullptr;
+ }
+ };
+#endif
+ // context switch
+ ::SwitchToFiber( fiber);
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ return detail::exchange( current()->from, nullptr);
+#else
+ return std::exchange( current()->from, nullptr);
+#endif
+ }
+
+ virtual void deallocate() noexcept {
+ }
+};
+
+struct BOOST_CONTEXT_DECL activation_record_initializer {
+ activation_record_initializer() noexcept;
+ ~activation_record_initializer();
+};
+
+struct forced_unwind {
+ activation_record * from{ nullptr };
+
+ explicit forced_unwind( activation_record * from_) :
+ from{ from_ } {
+ }
+};
+
+template< typename Ctx, typename StackAlloc, typename Fn >
+class capture_record : public activation_record {
+private:
+ StackAlloc salloc_;
+ typename std::decay< Fn >::type fn_;
+
+ static void destroy( capture_record * p) noexcept {
+ StackAlloc salloc = p->salloc_;
+ stack_context sctx = p->sctx;
+ // deallocate activation record
+ p->~capture_record();
+ // destroy stack with stack allocator
+ salloc.deallocate( sctx);
+ }
+
+public:
+ capture_record( stack_context sctx, StackAlloc salloc, Fn && fn) noexcept :
+ activation_record( sctx),
+ salloc_( salloc),
+ fn_( std::forward< Fn >( fn) ) {
+ }
+
+ void deallocate() noexcept override final {
+ BOOST_ASSERT( main_ctx || ( ! main_ctx && terminated) );
+ destroy( this);
+ }
+
+ void run() {
+ Ctx c{ from };
+ try {
+ // invoke context-function
+#if defined(BOOST_NO_CXX17_STD_INVOKE)
+ c = invoke( fn_, std::move( c) );
+#else
+ c = std::invoke( fn_, std::move( c) );
+#endif
+ } catch ( forced_unwind const& ex) {
+ c = Ctx{ ex.from };
+ }
+ // this context has finished its task
+ from = nullptr;
+ ontop = nullptr;
+ terminated = true;
+ force_unwind = false;
+ c.resume();
+ BOOST_ASSERT_MSG( false, "continuation already terminated");
+ }
+};
+
+template< typename Ctx, typename StackAlloc, typename Fn >
+static activation_record * create_context1( StackAlloc salloc, Fn && fn) {
+ typedef capture_record< Ctx, StackAlloc, Fn > capture_t;
+
+ auto sctx = salloc.allocate();
+ BOOST_ASSERT( ( sizeof( capture_t) ) < sctx.size);
+ // reserve space for control structure
+ void * storage = reinterpret_cast< void * >(
+ ( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) )
+ & ~ static_cast< uintptr_t >( 0xff) );
+ // placment new for control structure on context stack
+ capture_t * record = new ( storage) capture_t{
+ sctx, salloc, std::forward< Fn >( fn) };
+ // create user-context
+ record->fiber = ::CreateFiber( sctx.size, & detail::entry_func< capture_t >, record);
+ return record;
+}
+
+template< typename Ctx, typename StackAlloc, typename Fn >
+static activation_record * create_context2( preallocated palloc, StackAlloc salloc, Fn && fn) {
+ typedef capture_record< Ctx, StackAlloc, Fn > capture_t;
+
+ BOOST_ASSERT( ( sizeof( capture_t) ) < palloc.size);
+ // reserve space for control structure
+ void * storage = reinterpret_cast< void * >(
+ ( reinterpret_cast< uintptr_t >( palloc.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) )
+ & ~ static_cast< uintptr_t >( 0xff) );
+ // placment new for control structure on context stack
+ capture_t * record = new ( storage) capture_t{
+ palloc.sctx, salloc, std::forward< Fn >( fn) };
+ // create user-context
+ record->fiber = ::CreateFiber( palloc.sctx.size, & detail::entry_func< capture_t >, record);
+ return record;
+}
+
+}
+
+class BOOST_CONTEXT_DECL continuation {
+private:
+ friend struct detail::activation_record;
+
+ template< typename Ctx, typename StackAlloc, typename Fn >
+ friend class detail::capture_record;
+
+ template< typename Ctx, typename StackAlloc, typename Fn >
+ friend detail::activation_record * detail::create_context1( StackAlloc, Fn &&);
+
+ template< typename Ctx, typename StackAlloc, typename Fn >
+ friend detail::activation_record * detail::create_context2( preallocated, StackAlloc, Fn &&);
+
+ template< typename StackAlloc, typename Fn >
+ friend continuation
+ callcc( std::allocator_arg_t, StackAlloc, Fn &&);
+
+ template< typename StackAlloc, typename Fn >
+ friend continuation
+ callcc( std::allocator_arg_t, preallocated, StackAlloc, Fn &&);
+
+ detail::activation_record * ptr_{ nullptr };
+
+ continuation( detail::activation_record * ptr) noexcept :
+ ptr_{ ptr } {
+ }
+
+public:
+ continuation() = default;
+
+ ~continuation() {
+ if ( BOOST_UNLIKELY( nullptr != ptr_) && ! ptr_->main_ctx) {
+ if ( BOOST_LIKELY( ! ptr_->terminated) ) {
+ ptr_->force_unwind = true;
+ ptr_->resume();
+ BOOST_ASSERT( ptr_->terminated);
+ }
+ ptr_->deallocate();
+ }
+ }
+
+ continuation( continuation const&) = delete;
+ continuation & operator=( continuation const&) = delete;
+
+ continuation( continuation && other) noexcept :
+ ptr_{ nullptr } {
+ swap( other);
+ }
+
+ continuation & operator=( continuation && other) noexcept {
+ if ( BOOST_LIKELY( this != & other) ) {
+ ptr_ = other.ptr_;
+ other.ptr_ = nullptr;
+ }
+ return * this;
+ }
+
+ continuation resume() {
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ detail::activation_record * ptr = detail::exchange( ptr_, nullptr)->resume();
+#else
+ detail::activation_record * ptr = std::exchange( ptr_, nullptr)->resume();
+#endif
+ if ( BOOST_UNLIKELY( detail::activation_record::current()->force_unwind) ) {
+ throw detail::forced_unwind{ ptr};
+ } else if ( BOOST_UNLIKELY( nullptr != detail::activation_record::current()->ontop) ) {
+ detail::activation_record::current()->ontop( ptr);
+ detail::activation_record::current()->ontop = nullptr;
+ }
+ return continuation{ ptr };
+ }
+
+ template< typename Fn >
+ continuation resume_with( Fn && fn) {
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ detail::activation_record * ptr =
+ detail::exchange( ptr_, nullptr)->resume_with< continuation >( std::forward< Fn >( fn) );
+#else
+ detail::activation_record * ptr =
+ std::exchange( ptr_, nullptr)->resume_with< continuation >( std::forward< Fn >( fn) );
+#endif
+ if ( BOOST_UNLIKELY( detail::activation_record::current()->force_unwind) ) {
+ throw detail::forced_unwind{ ptr};
+ } else if ( BOOST_UNLIKELY( nullptr != detail::activation_record::current()->ontop) ) {
+ detail::activation_record::current()->ontop( ptr);
+ detail::activation_record::current()->ontop = nullptr;
+ }
+ return continuation{ ptr };
+ }
+
+ explicit operator bool() const noexcept {
+ return nullptr != ptr_ && ! ptr_->terminated;
+ }
+
+ bool operator!() const noexcept {
+ return nullptr == ptr_ || ptr_->terminated;
+ }
+
+ bool operator==( continuation const& other) const noexcept {
+ return ptr_ == other.ptr_;
+ }
+
+ bool operator!=( continuation const& other) const noexcept {
+ return ptr_ != other.ptr_;
+ }
+
+ bool operator<( continuation const& other) const noexcept {
+ return ptr_ < other.ptr_;
+ }
+
+ bool operator>( continuation const& other) const noexcept {
+ return other.ptr_ < ptr_;
+ }
+
+ bool operator<=( continuation const& other) const noexcept {
+ return ! ( * this > other);
+ }
+
+ bool operator>=( continuation const& other) const noexcept {
+ return ! ( * this < other);
+ }
+
+ template< typename charT, class traitsT >
+ friend std::basic_ostream< charT, traitsT > &
+ operator<<( std::basic_ostream< charT, traitsT > & os, continuation const& other) {
+ if ( nullptr != other.ptr_) {
+ return os << other.ptr_;
+ } else {
+ return os << "{not-a-context}";
+ }
+ }
+
+ void swap( continuation & other) noexcept {
+ std::swap( ptr_, other.ptr_);
+ }
+};
+
+template<
+ typename Fn,
+ typename = detail::disable_overload< continuation, Fn >
+>
+continuation
+callcc( Fn && fn) {
+ return callcc(
+ std::allocator_arg,
+ fixedsize_stack(),
+ std::forward< Fn >( fn) );
+}
+
+template< typename StackAlloc, typename Fn >
+continuation
+callcc( std::allocator_arg_t, StackAlloc salloc, Fn && fn) {
+ return continuation{
+ detail::create_context1< continuation >(
+ salloc, std::forward< Fn >( fn) ) }.resume();
+}
+
+template< typename StackAlloc, typename Fn >
+continuation
+callcc( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn) {
+ return continuation{
+ detail::create_context2< continuation >(
+ palloc, salloc, std::forward< Fn >( fn) ) }.resume();
+}
+
+inline
+void swap( continuation & l, continuation & r) noexcept {
+ l.swap( r);
+}
+
+}}
+
+#if defined(BOOST_MSVC)
+# pragma warning(pop)
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_CONTINUATION_H
diff --git a/boost/context/detail/config.hpp b/boost/context/detail/config.hpp
index 84dd238100..15d03574b1 100644
--- a/boost/context/detail/config.hpp
+++ b/boost/context/detail/config.hpp
@@ -104,4 +104,15 @@
# endif
#endif
+#if ! defined(BOOST_NO_CXX11_CONSTEXPR)
+// modern architectures have cachelines with 64byte length
+// ARM Cortex-A15 32/64byte, Cortex-A9 16/32/64bytes
+// MIPS 74K: 32byte, 4KEc: 16byte
+// ist should be safe to use 64byte for all
+static constexpr std::size_t cache_alignment{ 64 };
+static constexpr std::size_t cacheline_length{ 64 };
+// lookahead size for prefetching
+static constexpr std::size_t prefetch_stride{ 4 * cacheline_length };
+#endif
+
#endif // BOOST_CONTEXT_DETAIL_CONFIG_H
diff --git a/boost/context/detail/exception.hpp b/boost/context/detail/exception.hpp
index 8ffff6780a..14b4ab5217 100644
--- a/boost/context/detail/exception.hpp
+++ b/boost/context/detail/exception.hpp
@@ -20,7 +20,9 @@ namespace context {
namespace detail {
struct forced_unwind {
- fcontext_t fctx;
+ fcontext_t fctx{ nullptr };
+
+ forced_unwind() = default;
forced_unwind( fcontext_t fctx_) :
fctx( fctx_) {
diff --git a/boost/context/detail/fcontext_arm.hpp b/boost/context/detail/fcontext_arm.hpp
deleted file mode 100644
index 8b88ccfdd4..0000000000
--- a/boost/context/detail/fcontext_arm.hpp
+++ /dev/null
@@ -1,68 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the 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_CONTEXT_DETAIL_FCONTEXT_ARM_H
-#define BOOST_CONTEXT_DETAIL_FCONTEXT_ARM_H
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/context/detail/config.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-extern "C" {
-
-#define BOOST_CONTEXT_CALLDECL
-
-struct stack_t
-{
- void * sp;
- std::size_t size;
-
- stack_t() :
- sp( 0), size( 0)
- {}
-};
-
-struct fp_t
-{
- boost::uint32_t fc_freg[16];
-
- fp_t() :
- fc_freg()
- {}
-};
-
-struct fcontext_t
-{
- boost::uint32_t fc_greg[11];
- stack_t fc_stack;
- fp_t fc_fp;
-
- fcontext_t() :
- fc_greg(),
- fc_stack(),
- fc_fp()
- {}
-};
-
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_ARM_H
diff --git a/boost/context/detail/fcontext_arm_mac.hpp b/boost/context/detail/fcontext_arm_mac.hpp
deleted file mode 100644
index a8416efd0c..0000000000
--- a/boost/context/detail/fcontext_arm_mac.hpp
+++ /dev/null
@@ -1,70 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the 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_CONTEXT_DETAIL_FCONTEXT_ARM_MAC_H
-#define BOOST_CONTEXT_DETAIL_FCONTEXT_ARM_MAC_H
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/context/detail/config.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-extern "C" {
-
-#define BOOST_CONTEXT_CALLDECL
-
-struct stack_t
-{
- void * sp;
- std::size_t size;
-
- stack_t() :
- sp( 0), size( 0)
- {}
-};
-
-struct fp_t
-{
- boost::uint32_t fc_freg[16];
-
- fp_t() :
- fc_freg()
- {}
-};
-
-struct fcontext_t
-{
- boost::uint32_t fc_greg[11];
- stack_t fc_stack;
- fp_t fc_fp;
- void * fc_unwind_sjlj;
-
- fcontext_t() :
- fc_greg(),
- fc_stack(),
- fc_fp(),
- fc_unwind_sjlj( 0)
- {}
-};
-
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_ARM_MAC_H
diff --git a/boost/context/detail/fcontext_arm_win.hpp b/boost/context/detail/fcontext_arm_win.hpp
deleted file mode 100644
index 5449ae763f..0000000000
--- a/boost/context/detail/fcontext_arm_win.hpp
+++ /dev/null
@@ -1,71 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the 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_CONTEXT_DETAIL_FCONTEXT_ARM_WIN_H
-#define BOOST_CONTEXT_DETAIL_FCONTEXT_ARM_WIN_H
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/context/detail/config.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-extern "C" {
-
-#define BOOST_CONTEXT_CALLDECL
-
-struct stack_t
-{
- void * sp;
- std::size_t size;
- void * limit;
-
- stack_t() :
- sp( 0), size( 0), limit( 0)
- {}
-};
-
-struct fp_t
-{
- boost::uint32_t fc_freg[16];
-
- fp_t() :
- fc_freg()
- {}
-};
-
-struct fcontext_t
-{
- boost::uint32_t fc_greg[11];
- stack_t fc_stack;
- fp_t fc_fp;
- boost::uint32_t fc_dealloc;
-
- fcontext_t() :
- fc_greg(),
- fc_stack(),
- fc_fp(),
- fc_dealloc( 0)
- {}
-};
-
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_ARM_WIN_H
diff --git a/boost/context/detail/fcontext_i386.hpp b/boost/context/detail/fcontext_i386.hpp
deleted file mode 100644
index 2e01323556..0000000000
--- a/boost/context/detail/fcontext_i386.hpp
+++ /dev/null
@@ -1,59 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the 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_CONTEXT_DETAIL_FCONTEXT_I386H
-#define BOOST_CONTEXT_DETAIL_FCONTEXT_I386H
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/context/detail/config.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-extern "C" {
-
-#define BOOST_CONTEXT_CALLDECL __attribute__((cdecl))
-
-struct stack_t
-{
- void * sp;
- std::size_t size;
-
- stack_t() :
- sp( 0), size( 0)
- {}
-};
-
-struct fcontext_t
-{
- boost::uint32_t fc_greg[6];
- stack_t fc_stack;
- boost::uint32_t fc_freg[2];
-
- fcontext_t() :
- fc_greg(),
- fc_stack(),
- fc_freg()
- {}
-};
-
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_I386_H
diff --git a/boost/context/detail/fcontext_i386_win.hpp b/boost/context/detail/fcontext_i386_win.hpp
deleted file mode 100644
index 44c6b0ef56..0000000000
--- a/boost/context/detail/fcontext_i386_win.hpp
+++ /dev/null
@@ -1,88 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the 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_CONTEXT_DETAIL_FCONTEXT_I386H
-#define BOOST_CONTEXT_DETAIL_FCONTEXT_I386H
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/context/detail/config.hpp>
-
-#if defined(BOOST_MSVC)
-#pragma warning(push)
-#pragma warning(disable:4351)
-#endif
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-extern "C" {
-
-#define BOOST_CONTEXT_CALLDECL __cdecl
-
-struct stack_t
-{
- void * sp;
- std::size_t size;
- void * limit;
-
- stack_t() :
- sp( 0), size( 0), limit( 0)
- {}
-};
-
-struct fp_t
-{
- boost::uint32_t fc_freg[2];
-
- fp_t() :
- fc_freg()
- {}
-};
-
-struct fcontext_t
-{
- boost::uint32_t fc_greg[6];
- stack_t fc_stack;
- void * fc_excpt_lst;
- void * fc_local_storage;
- fp_t fc_fp;
- boost::uint32_t fc_dealloc;
-
- fcontext_t() :
- fc_greg(),
- fc_stack(),
- fc_excpt_lst( 0),
- fc_local_storage( 0),
- fc_fp(),
- fc_dealloc( 0)
- {}
-};
-
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#if defined(BOOST_MSVC)
-#pragma warning(pop)
-#endif
-
-#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_I386_H
diff --git a/boost/context/detail/fcontext_mips.hpp b/boost/context/detail/fcontext_mips.hpp
deleted file mode 100644
index d3cd60de48..0000000000
--- a/boost/context/detail/fcontext_mips.hpp
+++ /dev/null
@@ -1,70 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the 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_CONTEXT_DETAIL_FCONTEXT_MIPS_H
-#define BOOST_CONTEXT_DETAIL_FCONTEXT_MIPS_H
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/context/detail/config.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-extern "C" {
-
-#define BOOST_CONTEXT_CALLDECL
-
-// on MIPS we assume 64bit regsiters - even for 32bit ABIs
-
-struct stack_t
-{
- void * sp;
- std::size_t size;
-
- stack_t() :
- sp( 0), size( 0)
- {}
-};
-
-struct fp_t
-{
- boost::uint64_t fc_freg[6];
-
- fp_t() :
- fc_freg()
- {}
-};
-
-struct fcontext_t
-{
- boost::uint32_t fc_greg[12];
- stack_t fc_stack;
- fp_t fc_fp;
-
- fcontext_t() :
- fc_greg(),
- fc_stack(),
- fc_fp()
- {}
-};
-
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_MIPS_H
diff --git a/boost/context/detail/fcontext_ppc.hpp b/boost/context/detail/fcontext_ppc.hpp
deleted file mode 100644
index 6cb019f54f..0000000000
--- a/boost/context/detail/fcontext_ppc.hpp
+++ /dev/null
@@ -1,72 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the 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_CONTEXT_DETAIL_FCONTEXT_PPC_H
-#define BOOST_CONTEXT_DETAIL_FCONTEXT_PPC_H
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/context/detail/config.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-extern "C" {
-
-#define BOOST_CONTEXT_CALLDECL
-
-struct stack_t
-{
- void * sp;
- std::size_t size;
-
- stack_t() :
- sp( 0), size( 0)
- {}
-};
-
-struct fp_t
-{
- boost::uint64_t fc_freg[19];
-
- fp_t() :
- fc_freg()
- {}
-};
-
-struct fcontext_t
-{
-# if defined(__powerpc64__)
- boost::uint64_t fc_greg[23];
-# else
- boost::uint32_t fc_greg[23];
-# endif
- stack_t fc_stack;
- fp_t fc_fp;
-
- fcontext_t() :
- fc_greg(),
- fc_stack(),
- fc_fp()
- {}
-};
-
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_PPC_H
diff --git a/boost/context/detail/fcontext_sparc.hpp b/boost/context/detail/fcontext_sparc.hpp
deleted file mode 100644
index 9264714aee..0000000000
--- a/boost/context/detail/fcontext_sparc.hpp
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright Martin Husemann 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_CTX_DETAIL_FCONTEXT_SPARC_H
-#define BOOST_CTX_DETAIL_FCONTEXT_SPARC_H
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/context/detail/config.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-extern "C" {
-
-#define BOOST_CONTEXT_CALLDECL
-
-// if defined(_LP64) we are compiling for sparc64, otherwise it is 32 bit
-// sparc.
-
-
-struct stack_t
-{
- void * sp;
- std::size_t size;
-
- stack_t() :
- sp( 0), size( 0)
- {}
-};
-
-struct fp_t
-{
-#ifdef _LP64
- boost::uint64_t fp_freg[32];
- boost::uint64_t fp_fprs, fp_fsr;
-#else
- boost::uint64_t fp_freg[16];
- boost::uint32_t fp_fsr;
-#endif
-
- fp_t() :
- fp_freg(),
-#ifdef _LP64
- fp_fprs(),
-#endif
- fp_fsr()
- {}
-}
-#ifdef _LP64
- __attribute__((__aligned__(64))) // allow VIS instructions to be used
-#endif
-;
-
-struct fcontext_t
-{
- fp_t fc_fp; // fpu stuff first, for easier alignement
-#ifdef _LP64
- boost::uint64_t
-#else
- boost::uint32_t
-#endif
- fc_greg[8];
- stack_t fc_stack;
-
- fcontext_t() :
- fc_fp(),
- fc_greg(),
- fc_stack()
- {}
-};
-
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CTX_DETAIL_FCONTEXT_SPARC_H
diff --git a/boost/context/detail/fcontext_x86_64.hpp b/boost/context/detail/fcontext_x86_64.hpp
deleted file mode 100644
index 6e8d93c0cb..0000000000
--- a/boost/context/detail/fcontext_x86_64.hpp
+++ /dev/null
@@ -1,68 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the 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_CONTEXT_DETAIL_FCONTEXT_X86_64_H
-#define BOOST_CONTEXT_DETAIL_FCONTEXT_X86_64_H
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/context/detail/config.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-extern "C" {
-
-#define BOOST_CONTEXT_CALLDECL
-
-struct stack_t
-{
- void * sp;
- std::size_t size;
-
- stack_t() :
- sp( 0), size( 0)
- {}
-};
-
-struct fp_t
-{
- boost::uint32_t fc_freg[2];
-
- fp_t() :
- fc_freg()
- {}
-};
-
-struct fcontext_t
-{
- boost::uint64_t fc_greg[8];
- stack_t fc_stack;
- fp_t fc_fp;
-
- fcontext_t() :
- fc_greg(),
- fc_stack(),
- fc_fp()
- {}
-};
-
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_X86_64_H
diff --git a/boost/context/detail/fcontext_x86_64_win.hpp b/boost/context/detail/fcontext_x86_64_win.hpp
deleted file mode 100644
index 7bcea55fb3..0000000000
--- a/boost/context/detail/fcontext_x86_64_win.hpp
+++ /dev/null
@@ -1,77 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the 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_CONTEXT_DETAIL_FCONTEXT_X86_64_H
-#define BOOST_CONTEXT_DETAIL_FCONTEXT_X86_64_H
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/context/detail/config.hpp>
-
-#if defined(BOOST_MSVC)
-#pragma warning(push)
-#pragma warning(disable:4351)
-#endif
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-extern "C" {
-
-#define BOOST_CONTEXT_CALLDECL
-
-struct stack_t
-{
- void * sp;
- std::size_t size;
- void * limit;
-
- stack_t() :
- sp( 0), size( 0), limit( 0)
- {}
-};
-
-struct fcontext_t
-{
- boost::uint64_t fc_greg[10];
- stack_t fc_stack;
- void * fc_local_storage;
- boost::uint64_t fc_fp[24];
- boost::uint64_t fc_dealloc;
-
- fcontext_t() :
- fc_greg(),
- fc_stack(),
- fc_local_storage( 0),
- fc_fp(),
- fc_dealloc()
- {}
-};
-
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#if defined(BOOST_MSVC)
-#pragma warning(pop)
-#endif
-
-#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_X86_64_H
diff --git a/boost/context/detail/prefetch.hpp b/boost/context/detail/prefetch.hpp
new file mode 100644
index 0000000000..a479450c74
--- /dev/null
+++ b/boost/context/detail/prefetch.hpp
@@ -0,0 +1,78 @@
+// Copyright Oliver Kowalke 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_CONTEXT_DETAIL_PREFETCH_H
+#define BOOST_CONTEXT_DETAIL_PREFETCH_H
+
+#include <cstddef>
+#include <cstdint>
+
+#include <boost/config.hpp>
+#include <boost/predef.h>
+
+#include <boost/context/detail/config.hpp>
+
+#if BOOST_COMP_INTEL || BOOST_COMP_INTEL_EMULATED
+#include <immintrin.h>
+#endif
+
+#if BOOST_COMP_MSVC
+#include <mmintrin.h>
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+namespace detail {
+
+#if BOOST_COMP_GNUC || BOOST_COMP_CLANG
+#define BOOST_HAS_PREFETCH 1
+BOOST_FORCEINLINE
+void prefetch( void * addr) {
+ // L1 cache : hint == 1
+ __builtin_prefetch( addr, 1, 1);
+}
+#elif BOOST_COMP_INTEL || BOOST_COMP_INTEL_EMULATED
+#define BOOST_HAS_PREFETCH 1
+BOOST_FORCEINLINE
+void prefetch( void * addr) {
+ // L1 cache : hint == _MM_HINT_T0
+ _mm_prefetch( (const char *)addr, _MM_HINT_T0);
+}
+#elif BOOST_COMP_MSVC
+#define BOOST_HAS_PREFETCH 1
+BOOST_FORCEINLINE
+void prefetch( void * addr) {
+ // L1 cache : hint == _MM_HINT_T0
+ _mm_prefetch( (const char *)addr, _MM_HINT_T0);
+}
+#endif
+
+inline
+void prefetch_range( void * addr, std::size_t len) {
+#if defined(BOOST_HAS_PREFETCH)
+ void * vp = addr;
+ void * end = reinterpret_cast< void * >(
+ reinterpret_cast< uintptr_t >( addr) + static_cast< uintptr_t >( len) );
+ while ( vp < end) {
+ prefetch( vp);
+ vp = reinterpret_cast< void * >(
+ reinterpret_cast< uintptr_t >( vp) + static_cast< uintptr_t >( prefetch_stride) );
+ }
+#endif
+}
+
+#undef BOOST_HAS_PREFETCH
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_DETAIL_PREFETCH_H
diff --git a/boost/context/fixedsize_stack.hpp b/boost/context/fixedsize_stack.hpp
index 46e7866891..756b260bda 100644
--- a/boost/context/fixedsize_stack.hpp
+++ b/boost/context/fixedsize_stack.hpp
@@ -4,10 +4,77 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
+#ifndef BOOST_CONTEXT_FIXEDSIZE_H
+#define BOOST_CONTEXT_FIXEDSIZE_H
+
+#include <cstddef>
+#include <cstdlib>
+#include <new>
+
+#include <boost/assert.hpp>
#include <boost/config.hpp>
-#if defined(BOOST_WINDOWS)
-# include <boost/context/windows/fixedsize_stack.hpp>
-#else
-# include <boost/context/posix/fixedsize_stack.hpp>
+#include <boost/context/detail/config.hpp>
+#include <boost/context/stack_context.hpp>
+#include <boost/context/stack_traits.hpp>
+
+#if defined(BOOST_USE_VALGRIND)
+#include <valgrind/valgrind.h>
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
#endif
+
+namespace boost {
+namespace context {
+
+template< typename traitsT >
+class basic_fixedsize_stack {
+private:
+ std::size_t size_;
+
+public:
+ typedef traitsT traits_type;
+
+ basic_fixedsize_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW :
+ size_( size) {
+ }
+
+ stack_context allocate() {
+ void * vp = std::malloc( size_);
+ if ( ! vp) {
+ throw std::bad_alloc();
+ }
+ stack_context sctx;
+ sctx.size = size_;
+ sctx.sp = static_cast< char * >( vp) + sctx.size;
+#if defined(BOOST_USE_VALGRIND)
+ sctx.valgrind_stack_id = VALGRIND_STACK_REGISTER( sctx.sp, vp);
+#endif
+ return sctx;
+ }
+
+ void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
+ BOOST_ASSERT( sctx.sp);
+
+#if defined(BOOST_USE_VALGRIND)
+ VALGRIND_STACK_DEREGISTER( sctx.valgrind_stack_id);
+#endif
+ void * vp = static_cast< char * >( sctx.sp) - sctx.size;
+ std::free( vp);
+ }
+};
+
+typedef basic_fixedsize_stack< stack_traits > fixedsize_stack;
+# if ! defined(BOOST_USE_SEGMENTED_STACKS)
+typedef fixedsize_stack default_stack;
+# endif
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_FIXEDSIZE_H
diff --git a/boost/context/pooled_fixedsize_stack.hpp b/boost/context/pooled_fixedsize_stack.hpp
index 3c0953cd07..9c417fd7ce 100644
--- a/boost/context/pooled_fixedsize_stack.hpp
+++ b/boost/context/pooled_fixedsize_stack.hpp
@@ -14,6 +14,7 @@
#include <boost/assert.hpp>
#include <boost/config.hpp>
+#include <boost/intrusive_ptr.hpp>
#include <boost/pool/pool.hpp>
#include <boost/context/detail/config.hpp>
diff --git a/boost/context/posix/fixedsize_stack.hpp b/boost/context/posix/fixedsize_stack.hpp
deleted file mode 100644
index 756b260bda..0000000000
--- a/boost/context/posix/fixedsize_stack.hpp
+++ /dev/null
@@ -1,80 +0,0 @@
-
-// Copyright Oliver Kowalke 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_CONTEXT_FIXEDSIZE_H
-#define BOOST_CONTEXT_FIXEDSIZE_H
-
-#include <cstddef>
-#include <cstdlib>
-#include <new>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-
-#include <boost/context/detail/config.hpp>
-#include <boost/context/stack_context.hpp>
-#include <boost/context/stack_traits.hpp>
-
-#if defined(BOOST_USE_VALGRIND)
-#include <valgrind/valgrind.h>
-#endif
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-template< typename traitsT >
-class basic_fixedsize_stack {
-private:
- std::size_t size_;
-
-public:
- typedef traitsT traits_type;
-
- basic_fixedsize_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW :
- size_( size) {
- }
-
- stack_context allocate() {
- void * vp = std::malloc( size_);
- if ( ! vp) {
- throw std::bad_alloc();
- }
- stack_context sctx;
- sctx.size = size_;
- sctx.sp = static_cast< char * >( vp) + sctx.size;
-#if defined(BOOST_USE_VALGRIND)
- sctx.valgrind_stack_id = VALGRIND_STACK_REGISTER( sctx.sp, vp);
-#endif
- return sctx;
- }
-
- void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
- BOOST_ASSERT( sctx.sp);
-
-#if defined(BOOST_USE_VALGRIND)
- VALGRIND_STACK_DEREGISTER( sctx.valgrind_stack_id);
-#endif
- void * vp = static_cast< char * >( sctx.sp) - sctx.size;
- std::free( vp);
- }
-};
-
-typedef basic_fixedsize_stack< stack_traits > fixedsize_stack;
-# if ! defined(BOOST_USE_SEGMENTED_STACKS)
-typedef fixedsize_stack default_stack;
-# endif
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXT_FIXEDSIZE_H
diff --git a/boost/context/posix/protected_fixedsize_stack.hpp b/boost/context/posix/protected_fixedsize_stack.hpp
index f36d451b40..b0c7f7e675 100644
--- a/boost/context/posix/protected_fixedsize_stack.hpp
+++ b/boost/context/posix/protected_fixedsize_stack.hpp
@@ -49,15 +49,13 @@ public:
}
stack_context allocate() {
- // page at bottom will be used as guard-page
- const std::size_t pages(
- static_cast< std::size_t >(
- std::floor(
+ // calculate how many pages are required
+ const std::size_t pages(
+ static_cast< std::size_t >(
+ std::ceil(
static_cast< float >( size_) / traits_type::page_size() ) ) );
- BOOST_ASSERT_MSG( 2 <= pages, "at least two pages must fit into stack (one page is guard-page)");
- const std::size_t size__( pages * traits_type::page_size() );
- BOOST_ASSERT( 0 != size_ && 0 != size__);
- BOOST_ASSERT( size__ <= size_);
+ // add one page at bottom that will be used as guard-page
+ const std::size_t size__ = ( pages + 1) * traits_type::page_size();
// conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
#if defined(MAP_ANON)
diff --git a/boost/context/windows/fixedsize_stack.hpp b/boost/context/windows/fixedsize_stack.hpp
deleted file mode 100644
index a67c315c47..0000000000
--- a/boost/context/windows/fixedsize_stack.hpp
+++ /dev/null
@@ -1,80 +0,0 @@
-
-// Copyright Oliver Kowalke 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_CONTEXT_FIXEDSIZE_H
-#define BOOST_CONTEXT_FIXEDSIZE_H
-
-extern "C" {
-#include <windows.h>
-}
-
-#include <cmath>
-#include <cstddef>
-#include <new>
-
-#include <boost/config.hpp>
-
-#include <boost/context/detail/config.hpp>
-#include <boost/context/stack_context.hpp>
-#include <boost/context/stack_traits.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-template< typename traitsT >
-class basic_fixedsize_stack {
-private:
- std::size_t size_;
-
-public:
- typedef traitsT traits_type;
-
- basic_fixedsize_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW :
- size_( size) {
- }
-
- stack_context allocate() {
- // page at bottom will be used as guard-page
- const std::size_t pages(
- static_cast< std::size_t >(
- std::floor(
- static_cast< float >( size_) / traits_type::page_size() ) ) );
- BOOST_ASSERT_MSG( 1 <= pages, "at least one page must fit into stack");
- const std::size_t size__( pages * traits_type::page_size() );
- BOOST_ASSERT( 0 != size_ && 0 != size__);
- BOOST_ASSERT( size__ <= size_);
-
- void * vp = ::VirtualAlloc( 0, size__, MEM_COMMIT, PAGE_READWRITE);
- if ( ! vp) throw std::bad_alloc();
-
- stack_context sctx;
- sctx.size = size__;
- sctx.sp = static_cast< char * >( vp) + sctx.size;
- return sctx;
- }
-
- void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
- BOOST_ASSERT( sctx.sp);
-
- void * vp = static_cast< char * >( sctx.sp) - sctx.size;
- ::VirtualFree( vp, 0, MEM_RELEASE);
- }
-};
-
-typedef basic_fixedsize_stack< stack_traits > fixedsize_stack;
-typedef fixedsize_stack default_stack;
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXT_FIXEDSIZE_H
diff --git a/boost/context/windows/protected_fixedsize_stack.hpp b/boost/context/windows/protected_fixedsize_stack.hpp
index 437f091088..26d2086095 100644
--- a/boost/context/windows/protected_fixedsize_stack.hpp
+++ b/boost/context/windows/protected_fixedsize_stack.hpp
@@ -41,15 +41,13 @@ public:
}
stack_context allocate() {
- // page at bottom will be used as guard-page
- const std::size_t pages(
- static_cast< std::size_t >(
- std::floor(
+ // calculate how many pages are required
+ const std::size_t pages(
+ static_cast< std::size_t >(
+ std::ceil(
static_cast< float >( size_) / traits_type::page_size() ) ) );
- BOOST_ASSERT_MSG( 2 <= pages, "at least two pages must fit into stack (one page is guard-page)");
- const std::size_t size__( pages * traits_type::page_size() );
- BOOST_ASSERT( 0 != size_ && 0 != size__);
- BOOST_ASSERT( size__ <= size_);
+ // add one page at bottom that will be used as guard-page
+ const std::size_t size__ = ( pages + 1) * traits_type::page_size();
void * vp = ::VirtualAlloc( 0, size__, MEM_COMMIT, PAGE_READWRITE);
if ( ! vp) throw std::bad_alloc();
diff --git a/boost/convert.hpp b/boost/convert.hpp
index 8bb93b5912..efde44ff7b 100644
--- a/boost/convert.hpp
+++ b/boost/convert.hpp
@@ -18,7 +18,7 @@
// as they should;
// 5. Paul Bristow for helping great deal with the documentation;
// 6. Kevlin Henney and Dave Abrahams for their lexical_cast-related insights and explanations.
-//
+//
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
@@ -32,9 +32,8 @@ namespace boost
{
namespace detail { enum throw_on_failure {}; }
- /// @details The boost::throw_on_failure is the name of an object of the
- /// boost::detail::throw_on_failure type that is used to indicate
- /// desired exception-throwing behavior.
+ /// @details boost::throw_on_failure is the 'tag' object
+ /// to request the exception-throwing behavior.
detail::throw_on_failure const throw_on_failure = detail::throw_on_failure(0);
namespace cnv
@@ -44,7 +43,7 @@ namespace boost
}
/// @brief Boost.Convert main deployment interface
- /// @param[in] value_in Value of the TypeIn type to be converted to the TyeOut type
+ /// @param[in] value_in Value of the TypeIn type to be converted to the TypeOut type
/// @param[in] converter Converter to be used for conversion
/// @return boost::optional<TypeOut> result of conversion together with the indication of
/// success or failure of the conversion request.
@@ -79,7 +78,7 @@ namespace boost
/// @brief Boost.Convert deployment interface with the default converter
/// @details For example,
/// @code
- /// struct boost::cnv::by_default : public boost::cnv::cstream {};
+ /// struct boost::cnv::by_default : boost::cnv::cstream {};
///
/// // boost::cnv::cstream (through boost::cnv::by_default) is deployed
/// // as the default converter when no converter is provided explicitly.
diff --git a/boost/convert/base.hpp b/boost/convert/base.hpp
index 27931194cc..678d99cfc6 100644
--- a/boost/convert/base.hpp
+++ b/boost/convert/base.hpp
@@ -7,7 +7,6 @@
#include <boost/convert/parameters.hpp>
#include <boost/convert/detail/is_string.hpp>
-#include <cctype>
#include <cstring>
namespace boost { namespace cnv
@@ -106,19 +105,13 @@ struct boost::cnv::cnvbase
void
str_to_(string_type const& str, optional<out_type>& result_out) const
{
- using range_type = cnv::range<string_type const>;
- using char_type = typename range_type::value_type;
+ cnv::range<string_type const> range (str);
- range_type range (str);
- auto is_space = [](char_type ch)
- {
- return std::isspace(static_cast<unsigned char>(ch));
- };
if (skipws_)
- for (; !range.empty() && is_space(*range.begin()); ++range);
+ for (; !range.empty() && cnv::is_space(*range.begin()); ++range);
- if (range.empty()) return;
- if (is_space(*range.begin())) return;
+ if (range.empty()) return;
+ if (cnv::is_space(*range.begin())) return;
dncast().str_to(range, result_out);
}
@@ -126,35 +119,31 @@ struct boost::cnv::cnvbase
void
to_str_(in_type value_in, optional<string_type>& result_out) const
{
- using range_type = cnv::range<string_type>;
- using char_type = typename range_type::value_type;
+ using char_type = typename cnv::range<string_type>::value_type;
+ using range_type = cnv::range<char_type*>;
+ using buf_type = char_type[bufsize_];
- char_type buf[bufsize_];
- cnv::range<char_type*> range = dncast().to_str(value_in, buf);
- char_type* beg = range.begin();
- char_type* end = range.end();
+ buf_type buf;
+ range_type range = dncast().to_str(value_in, buf);
+ char_type* beg = range.begin();
+ char_type* end = range.end();
+ int str_size = end - beg;
- if (beg < end)
- format_(buf, beg, end), result_out = string_type(beg, end);
- }
+ if (str_size <= 0)
+ return;
- template<typename char_type>
- void
- format_(char_type* buf, char_type*& beg, char_type*& end) const
- {
if (uppercase_)
- for (char_type* p = beg; p < end; ++p) *p = std::toupper(*p);
+ for (char_type* p = beg; p < end; ++p) *p = cnv::to_upper(*p);
if (width_)
{
- int num_fillers = (std::max)(0, int(width_ - (end - beg)));
- int num_left = adjust_ == boost::cnv::adjust::left ? 0
- : adjust_ == boost::cnv::adjust::right ? num_fillers
- : (num_fillers / 2);
- int num_right = num_fillers - num_left;
- int str_size = end - beg;
- bool move = (beg < buf + num_left) // No room for left fillers
- || (buf + bufsize_ < end + num_right); // No room for right fillers
+ int num_fill = (std::max)(0, int(width_ - (end - beg)));
+ int num_left = adjust_ == cnv::adjust::left ? 0
+ : adjust_ == cnv::adjust::right ? num_fill
+ : (num_fill / 2);
+ int num_right = num_fill - num_left;
+ bool move = (beg < buf + num_left) // No room for left fillers
+ || (buf + bufsize_ < end + num_right); // No room for right fillers
if (move)
{
std::memmove(buf + num_left, beg, str_size * sizeof(char_type));
@@ -164,6 +153,7 @@ struct boost::cnv::cnvbase
for (int k = 0; k < num_left; *(--beg) = fill_, ++k);
for (int k = 0; k < num_right; *(end++) = fill_, ++k);
}
+ result_out = string_type(beg, end);
}
derived_type const& dncast () const { return *static_cast<derived_type const*>(this); }
diff --git a/boost/convert/detail/char.hpp b/boost/convert/detail/char.hpp
index 1d375bad51..a829dc8806 100644
--- a/boost/convert/detail/char.hpp
+++ b/boost/convert/detail/char.hpp
@@ -5,18 +5,34 @@
#ifndef BOOST_CONVERT_DETAIL_IS_CHAR_HPP
#define BOOST_CONVERT_DETAIL_IS_CHAR_HPP
-#include <boost/mpl/bool.hpp>
-#include <boost/type_traits/remove_const.hpp>
+#include <boost/convert/detail/config.hpp>
+#include <type_traits>
+#include <cctype>
+#include <cwctype>
namespace boost { namespace cnv
{
+ using char_type = char;
+ using uchar_type = unsigned char;
+ using wchar_type = wchar_t;
+
namespace detail
{
- template<typename T> struct is_char : mpl::false_ {};
- template<> struct is_char<char> : mpl:: true_ {};
- template<> struct is_char<wchar_t> : mpl:: true_ {};
+ template<typename> struct is_char : std::false_type {};
+ template<> struct is_char< char_type> : std:: true_type {};
+ template<> struct is_char<wchar_type> : std:: true_type {};
}
- template <typename T> struct is_char : detail::is_char<typename remove_const<T>::type> {};
+ template <typename T> struct is_char : detail::is_char<typename boost::remove_const<T>::type> {};
+
+ template<typename char_type> inline bool is_space(char_type);
+ template<typename char_type> inline char_type to_upper(char_type);
+
+ template<> inline bool is_space ( char_type c) { return bool(std::isspace(static_cast<uchar_type>(c))); }
+ template<> inline bool is_space (uchar_type c) { return bool(std::isspace(c)); }
+ template<> inline bool is_space (wchar_type c) { return bool(std::iswspace(c)); }
+ template<> inline char_type to_upper ( char_type c) { return std::toupper(static_cast<uchar_type>(c)); }
+ template<> inline uchar_type to_upper (uchar_type c) { return std::toupper(c); }
+ template<> inline wchar_type to_upper (wchar_type c) { return std::towupper(c); }
}}
#endif // BOOST_CONVERT_DETAIL_IS_CHAR_HPP
diff --git a/boost/convert/detail/forward.hpp b/boost/convert/detail/config.hpp
index 7ea7960490..6c74cd308a 100644
--- a/boost/convert/detail/forward.hpp
+++ b/boost/convert/detail/config.hpp
@@ -5,7 +5,33 @@
#ifndef BOOST_CONVERT_FORWARD_HPP
#define BOOST_CONVERT_FORWARD_HPP
+#include <boost/config.hpp>
+#include <boost/version.hpp>
+#include <boost/optional.hpp>
+
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+#undef BOOST_CONVERT_CXX11
+#else
+#define BOOST_CONVERT_CXX11
+#endif
+
+// Intel 12.0 and lower have broken SFINAE
+#if defined(BOOST_INTEL) && (BOOST_INTEL <= 1200)
+# define BOOST_CONVERT_IS_NOT_SUPPORTED
+#endif
+
+// No C++11 support
+#if defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION <= 40600)
+# define BOOST_CONVERT_IS_NOT_SUPPORTED
+#endif
+
+// MSVC-11 and lower have broken SFINAE
+#if defined(BOOST_MSVC) && (BOOST_MSVC < 1800)
+# define BOOST_CONVERT_IS_NOT_SUPPORTED
+#endif
+
#if defined(_MSC_VER)
+
//MSVC++ 7.0 _MSC_VER == 1300
//MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio 2003)
//MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
@@ -29,23 +55,4 @@
#endif
-#include <boost/config.hpp>
-#include <boost/version.hpp>
-#include <boost/optional.hpp>
-
-#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
-#undef BOOST_CONVERT_CXX11
-#else
-#define BOOST_CONVERT_CXX11
-#endif
-
-#if defined(BOOST_INTEL) && (BOOST_INTEL <= 1200) /* Intel 12.0 and lower have broken SFINAE */
-#error "Boost.Convert is not supported on this platform due to broken SFINAE."
-#endif
-
-#if defined(BOOST_MSVC) && (BOOST_MSVC < 1800) /* MSVC-11 and lower have broken SFINAE */
-//# error "Boost.Convert is not supported on this platform due to broken SFINAE."
-# define BOOST_CONVERT_MSVC_SFINAE_BROKEN
-#endif
-
#endif // BOOST_CONVERT_FORWARD_HPP
diff --git a/boost/convert/detail/has_member.hpp b/boost/convert/detail/has_member.hpp
index 68e53807a9..2cd617f7b0 100644
--- a/boost/convert/detail/has_member.hpp
+++ b/boost/convert/detail/has_member.hpp
@@ -5,7 +5,6 @@
#ifndef BOOST_CONVERT_HAS_MEMBER_HPP
#define BOOST_CONVERT_HAS_MEMBER_HPP
-#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/detail/yes_no_type.hpp>
// This macro allows to check if a type has a member named "__member_name__"...
@@ -41,7 +40,7 @@
template <typename __boost_has_member_T__> /*C4*/ \
class __trait_name__ \
{ \
- typedef typename ::boost::remove_const<__boost_has_member_T__>::type check_type; \
+ typedef typename boost::remove_const<__boost_has_member_T__>::type check_type; \
typedef ::boost::type_traits::yes_type yes_type; \
typedef ::boost::type_traits:: no_type no_type; \
\
diff --git a/boost/convert/detail/is_converter.hpp b/boost/convert/detail/is_converter.hpp
index 7633b6daba..6964655409 100644
--- a/boost/convert/detail/is_converter.hpp
+++ b/boost/convert/detail/is_converter.hpp
@@ -5,7 +5,7 @@
#ifndef BOOST_CONVERT_IS_CONVERTER_HPP
#define BOOST_CONVERT_IS_CONVERTER_HPP
-#include <boost/convert/detail/forward.hpp>
+#include <boost/convert/detail/config.hpp>
#include <boost/convert/detail/is_callable.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>
diff --git a/boost/convert/detail/is_fun.hpp b/boost/convert/detail/is_fun.hpp
index 9fa4d96f9b..72a768188a 100644
--- a/boost/convert/detail/is_fun.hpp
+++ b/boost/convert/detail/is_fun.hpp
@@ -5,7 +5,7 @@
#ifndef BOOST_CONVERT_IS_FUNCTION_HPP
#define BOOST_CONVERT_IS_FUNCTION_HPP
-#include <boost/convert/detail/forward.hpp>
+#include <boost/convert/detail/config.hpp>
#include <boost/convert/detail/has_member.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>
diff --git a/boost/convert/detail/is_string.hpp b/boost/convert/detail/is_string.hpp
index ea6ca82e90..75d565e3e7 100644
--- a/boost/convert/detail/is_string.hpp
+++ b/boost/convert/detail/is_string.hpp
@@ -11,7 +11,7 @@ namespace boost { namespace cnv
{
namespace detail
{
- template<typename T, bool is_range_class> struct is_string : mpl::false_ {};
+ template<typename T, bool is_range_class> struct is_string : std::false_type {};
template<typename T> struct is_string<T*, false>
{
@@ -27,7 +27,7 @@ namespace boost { namespace cnv
};
}
template<typename T> struct is_string : detail::is_string<
- typename remove_const<T>::type,
+ typename boost::remove_const<T>::type,
boost::is_class<T>::value && boost::cnv::is_range<T>::value> {};
}}
diff --git a/boost/convert/detail/range.hpp b/boost/convert/detail/range.hpp
index 345321039e..82d105f949 100644
--- a/boost/convert/detail/range.hpp
+++ b/boost/convert/detail/range.hpp
@@ -14,7 +14,7 @@ namespace boost { namespace cnv
{
namespace detail
{
- template<typename T, bool is_class> struct is_range : mpl::false_ {};
+ template<typename T, bool is_class> struct is_range : std::false_type {};
template<typename T> struct is_range<T, /*is_class=*/true>
{
@@ -24,7 +24,7 @@ namespace boost { namespace cnv
static bool const value = has_begin<T>::value && has_end<T>::value;
};
}
- template<typename T> struct is_range : detail::is_range<typename remove_const<T>::type, boost::is_class<T>::value> {};
+ template<typename T> struct is_range : detail::is_range<typename boost::remove_const<T>::type, boost::is_class<T>::value> {};
template<typename T, typename enable =void> struct range;
template<typename T, typename enable =void> struct iterator;
@@ -38,9 +38,9 @@ namespace boost { namespace cnv
template<typename T>
struct iterator<T*, void>
{
- typedef typename remove_const<T>::type value_type;
- typedef T* type;
- typedef value_type const* const_type;
+ typedef typename boost::remove_const<T>::type value_type;
+ typedef T* type;
+ typedef value_type const* const_type;
};
template<typename T>
struct range_base
@@ -74,20 +74,21 @@ namespace boost { namespace cnv
range (T& r) : base_type(r.begin(), r.end()) {}
- iterator end () { return base_type::end_; }
- const_iterator end () const { return base_type::end_; }
- sentry_type sentry () const { return base_type::end_; }
- bool empty () const { return base_type::begin_ == base_type::end_; }
+ iterator end () { return base_type::end_; }
+ const_iterator end () const { return base_type::end_; }
+ sentry_type sentry () const { return base_type::end_; }
+ std::size_t size () const { return base_type::end_ - base_type::begin_; }
+ bool empty () const { return base_type::begin_ == base_type::end_; }
};
template<typename T>
struct range<T*, typename enable_if<cnv::is_char<T> >::type> : public range_base<T*>
{
- typedef range this_type;
- typedef range_base<T*> base_type;
- typedef typename remove_const<T>::type value_type;
- typedef T* iterator;
- typedef value_type const* const_iterator;
+ using this_type = range;
+ using base_type = range_base<T*>;
+ using value_type = typename boost::remove_const<T>::type;
+ using iterator = T*;
+ using const_iterator = value_type const*;
struct sentry_type
{
diff --git a/boost/convert/spirit.hpp b/boost/convert/spirit.hpp
index 22a88b9b3f..b33a793f38 100644
--- a/boost/convert/spirit.hpp
+++ b/boost/convert/spirit.hpp
@@ -6,7 +6,7 @@
#define BOOST_CONVERT_SPIRIT_BASED_CONVERTER_HPP
#include <boost/convert/base.hpp>
-#include <boost/convert/detail/forward.hpp>
+#include <boost/convert/detail/config.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
diff --git a/boost/convert/strtol.hpp b/boost/convert/strtol.hpp
index de5aa29a8a..4dd26eef7f 100644
--- a/boost/convert/strtol.hpp
+++ b/boost/convert/strtol.hpp
@@ -76,16 +76,16 @@ boost::cnv::strtol::i_to_str(Type in_value, char_type* buf) const
typedef typename boost::make_unsigned<Type>::type unsigned_type;
- char_type* beg = buf + bufsize_ / 2;
- char_type* end = beg;
- bool const is_negative = in_value < 0;
- unsigned_type value = static_cast<unsigned_type>(is_negative ? -in_value : in_value);
+ char_type* beg = buf + bufsize_ / 2;
+ char_type* end = beg;
+ bool const is_neg = std::is_signed<Type>::value && in_value < 0;
+ unsigned_type value = static_cast<unsigned_type>(is_neg ? -in_value : in_value);
if (base_ == 10) for (; value; *(--beg) = int(value % 10) + '0', value /= 10); //C1
else for (; value; *(--beg) = get_char(value % base_), value /= base_);
- if (beg == end) *(--beg) = '0';
- if (is_negative) *(--beg) = '-';
+ if (beg == end) *(--beg) = '0';
+ if (is_neg) *(--beg) = '-';
return cnv::range<char_type*>(beg, end);
}
@@ -197,20 +197,20 @@ template<typename string_type, typename out_type>
void
boost::cnv::strtol::str_to_d(cnv::range<string_type> range, optional<out_type>& result_out) const
{
- // C2. Simply check if the end-of-string was reached -- *cnv_end == 0
- // instead of traversing once with strlen() to find the end iterator
- // and then comparing to it as in
- // char const* end = str + strlen(str); // Unnecessary traversal!
- // bool const good = ... && cnv_end == end;
+ // C1. Because of strtold() currently only works with 'char'
+ // C2. strtold() does not work with ranges.
+ // Consequently, we have to copy the supplied range into a string for strtold().
+ // C3. Check if the end-of-string was reached -- *cnv_end == 0.
typedef cnv::range<string_type> range_type;
typedef typename range_type::value_type ch_type;
- ch_type const* str = &*range.begin(); // Currently only works with 'char'
- char* cnv_end = 0;
- ldbl_type result = strtold(str, &cnv_end);
- bool good = result != -HUGE_VALL && result != HUGE_VALL && *cnv_end == 0/*C2*/;
- out_type max = (std::numeric_limits<out_type>::max)();
+ size_t const sz = 128;
+ ch_type str[sz] = {0}; std::strncpy(str, &*range.begin(), std::min(sz - 1, range.size()));
+ char* cnv_end = 0;
+ ldbl_type result = strtold(str, &cnv_end);
+ bool good = result != -HUGE_VALL && result != HUGE_VALL && *cnv_end == 0; //C3
+ out_type max = (std::numeric_limits<out_type>::max)();
if (good && -max <= result && result <= max)
result_out = out_type(result);
diff --git a/boost/core/addressof.hpp b/boost/core/addressof.hpp
index 0a2b46be77..8ddda8be4a 100644
--- a/boost/core/addressof.hpp
+++ b/boost/core/addressof.hpp
@@ -42,7 +42,7 @@ addressof(T& o) BOOST_NOEXCEPT
} /* boost */
#else
-#include <boost/detail/workaround.hpp>
+#include <boost/config/workaround.hpp>
#include <cstddef>
namespace boost {
@@ -117,7 +117,6 @@ struct address_of<const volatile addressof_null_t> {
} /* detail */
#if defined(BOOST_NO_CXX11_SFINAE_EXPR) || \
- defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \
defined(BOOST_NO_CXX11_CONSTEXPR) || \
defined(BOOST_NO_CXX11_DECLTYPE)
#define BOOST_CORE_NO_CONSTEXPR_ADDRESSOF
@@ -171,7 +170,7 @@ const T (*addressof(const T (&o)[N]) BOOST_NOEXCEPT)[N]
namespace detail {
template<class T>
-T&& addressof_declval() BOOST_NOEXCEPT;
+T addressof_declval() BOOST_NOEXCEPT;
template<class>
struct addressof_void {
@@ -262,4 +261,14 @@ addressof(T& o) BOOST_NOEXCEPT
} /* boost */
#endif
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
+ !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
+namespace boost {
+
+template<class T>
+const T* addressof(const T&&) = delete;
+
+} /* boost */
+#endif
+
#endif
diff --git a/boost/core/lightweight_test.hpp b/boost/core/lightweight_test.hpp
index b580dd2fa6..603e905bb5 100644
--- a/boost/core/lightweight_test.hpp
+++ b/boost/core/lightweight_test.hpp
@@ -19,12 +19,13 @@
// http://www.boost.org/LICENSE_1_0.txt
//
-#include <iterator>
+#include <boost/core/no_exceptions_support.hpp>
#include <boost/assert.hpp>
#include <boost/current_function.hpp>
-#include <boost/core/no_exceptions_support.hpp>
#include <iostream>
+#include <iterator>
#include <cstring>
+#include <cstddef>
// IDE's like Visual Studio perform better if output goes to std::cout or
// some other stream, so allow user to configure output stream:
@@ -113,6 +114,10 @@ inline const void* test_output_impl(unsigned char* v) { return v; }
inline const void* test_output_impl(signed char* v) { return v; }
template<class T> inline const void* test_output_impl(T volatile* v) { return const_cast<T*>(v); }
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+inline const void* test_output_impl(std::nullptr_t v) { return v; }
+#endif
+
template<class T, class U> inline void test_eq_impl( char const * expr1, char const * expr2,
char const * file, int line, char const * function, T const & t, U const & u )
{
@@ -147,6 +152,74 @@ template<class T, class U> inline void test_ne_impl( char const * expr1, char co
}
}
+template<class T, class U> inline void test_lt_impl( char const * expr1, char const * expr2,
+ char const * file, int line, char const * function, T const & t, U const & u )
+{
+ if( t < u )
+ {
+ report_errors_remind();
+ }
+ else
+ {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM
+ << file << "(" << line << "): test '" << expr1 << " < " << expr2
+ << "' failed in function '" << function << "': "
+ << "'" << test_output_impl(t) << "' >= '" << test_output_impl(u) << "'" << std::endl;
+ ++test_errors();
+ }
+}
+
+template<class T, class U> inline void test_le_impl( char const * expr1, char const * expr2,
+ char const * file, int line, char const * function, T const & t, U const & u )
+{
+ if( t <= u )
+ {
+ report_errors_remind();
+ }
+ else
+ {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM
+ << file << "(" << line << "): test '" << expr1 << " <= " << expr2
+ << "' failed in function '" << function << "': "
+ << "'" << test_output_impl(t) << "' > '" << test_output_impl(u) << "'" << std::endl;
+ ++test_errors();
+ }
+}
+
+template<class T, class U> inline void test_gt_impl( char const * expr1, char const * expr2,
+ char const * file, int line, char const * function, T const & t, U const & u )
+{
+ if( t > u )
+ {
+ report_errors_remind();
+ }
+ else
+ {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM
+ << file << "(" << line << "): test '" << expr1 << " > " << expr2
+ << "' failed in function '" << function << "': "
+ << "'" << test_output_impl(t) << "' <= '" << test_output_impl(u) << "'" << std::endl;
+ ++test_errors();
+ }
+}
+
+template<class T, class U> inline void test_ge_impl( char const * expr1, char const * expr2,
+ char const * file, int line, char const * function, T const & t, U const & u )
+{
+ if( t >= u )
+ {
+ report_errors_remind();
+ }
+ else
+ {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM
+ << file << "(" << line << "): test '" << expr1 << " >= " << expr2
+ << "' failed in function '" << function << "': "
+ << "'" << test_output_impl(t) << "' < '" << test_output_impl(u) << "'" << std::endl;
+ ++test_errors();
+ }
+}
+
inline void test_cstr_eq_impl( char const * expr1, char const * expr2,
char const * file, int line, char const * function, char const * const t, char const * const u )
{
@@ -360,6 +433,11 @@ inline int report_errors()
#define BOOST_TEST_EQ(expr1,expr2) ( ::boost::detail::test_eq_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
#define BOOST_TEST_NE(expr1,expr2) ( ::boost::detail::test_ne_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
+#define BOOST_TEST_LT(expr1,expr2) ( ::boost::detail::test_lt_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
+#define BOOST_TEST_LE(expr1,expr2) ( ::boost::detail::test_le_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
+#define BOOST_TEST_GT(expr1,expr2) ( ::boost::detail::test_gt_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
+#define BOOST_TEST_GE(expr1,expr2) ( ::boost::detail::test_ge_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
+
#define BOOST_TEST_CSTR_EQ(expr1,expr2) ( ::boost::detail::test_cstr_eq_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
#define BOOST_TEST_CSTR_NE(expr1,expr2) ( ::boost::detail::test_cstr_ne_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
diff --git a/boost/core/no_exceptions_support.hpp b/boost/core/no_exceptions_support.hpp
index a697f01a52..e2453d084b 100644
--- a/boost/core/no_exceptions_support.hpp
+++ b/boost/core/no_exceptions_support.hpp
@@ -21,7 +21,7 @@
//----------------------------------------------------------------------
#include <boost/config.hpp>
-#include <boost/detail/workaround.hpp>
+#include <boost/config/workaround.hpp>
#if !(defined BOOST_NO_EXCEPTIONS)
# define BOOST_TRY { try
diff --git a/boost/core/pointer_traits.hpp b/boost/core/pointer_traits.hpp
new file mode 100644
index 0000000000..ff1a5321db
--- /dev/null
+++ b/boost/core/pointer_traits.hpp
@@ -0,0 +1,258 @@
+/*
+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)
+*/
+#ifndef BOOST_CORE_POINTER_TRAITS_HPP
+#define BOOST_CORE_POINTER_TRAITS_HPP
+
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_POINTER_TRAITS)
+#include <memory>
+#else
+#include <boost/core/addressof.hpp>
+#endif
+
+namespace boost {
+
+template<class T>
+struct pointer_traits;
+
+namespace detail {
+
+template<class U>
+inline typename boost::pointer_traits<U>::element_type*
+ptr_traits_address(const U& v) BOOST_NOEXCEPT
+{
+ return boost::pointer_traits<U>::to_address(v);
+}
+
+} /* detail */
+
+#if !defined(BOOST_NO_CXX11_POINTER_TRAITS)
+template<class T>
+struct pointer_traits
+ : std::pointer_traits<T> {
+ template<class U>
+ struct rebind_to {
+ typedef typename std::pointer_traits<T>::template rebind<U> type;
+ };
+ static typename std::pointer_traits<T>::element_type*
+ to_address(const T& v) BOOST_NOEXCEPT {
+ return detail::ptr_traits_address(v.operator->());
+ }
+};
+
+template<class T>
+struct pointer_traits<T*>
+ : std::pointer_traits<T*> {
+ template<class U>
+ struct rebind_to {
+ typedef U* type;
+ };
+ static T* to_address(T* v) BOOST_NOEXCEPT {
+ return v;
+ }
+};
+#else
+namespace detail {
+
+struct ptr_traits_none { char first, second; };
+
+template<class T>
+struct ptr_traits_has_element {
+private:
+ template<class U>
+ static ptr_traits_none call(...);
+ template<class U>
+ static char call(typename U::element_type* = 0);
+public:
+ static const bool value = sizeof(call<T>(0)) == 1;
+};
+
+template<class T>
+struct ptr_traits_first;
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+template<template<class, class...> class T, class U, class... Args>
+struct ptr_traits_first<T<U, Args...> > {
+ typedef U type;
+};
+#else
+template<template<class> class T, class U>
+struct ptr_traits_first<T<U> > {
+ typedef U type;
+};
+
+template<template<class, class> class T, class U1, class U2>
+struct ptr_traits_first<T<U1, U2> > {
+ typedef U1 type;
+};
+
+template<template<class, class, class> class T, class U1, class U2, class U3>
+struct ptr_traits_first<T<U1, U2, U3> > {
+ typedef U1 type;
+};
+#endif
+
+template<class T, bool = ptr_traits_has_element<T>::value>
+struct ptr_traits_element {
+ typedef typename T::element_type type;
+};
+
+template<class T>
+struct ptr_traits_element<T, false> {
+ typedef typename ptr_traits_first<T>::type type;
+};
+
+template<class T>
+struct ptr_traits_has_difference {
+private:
+ template<class U>
+ static ptr_traits_none call(...);
+ template<class U>
+ static char call(typename U::difference_type* = 0);
+public:
+ static const bool value = sizeof(call<T>(0)) == 1;
+};
+
+template<class T, bool = ptr_traits_has_difference<T>::value>
+struct ptr_traits_difference {
+ typedef typename T::difference_type type;
+};
+
+template<class T>
+struct ptr_traits_difference<T, false> {
+ typedef std::ptrdiff_t type;
+};
+
+template<class T, class V>
+struct ptr_traits_has_rebind {
+private:
+ template<class U>
+ static ptr_traits_none call(...);
+ template<class U>
+ static char call(typename U::template rebind<V>* = 0);
+public:
+ static const bool value = sizeof(call<T>(0)) == 1;
+};
+
+template<class T, class V>
+struct ptr_traits_rebind_to;
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+template<template<class, class...> class T, class U, class... Args, class V>
+struct ptr_traits_rebind_to<T<U, Args...>, V> {
+ typedef T<V, Args...> type;
+};
+#else
+template<template<class> class T, class U, class V>
+struct ptr_traits_rebind_to<T<U>, V> {
+ typedef T<V> type;
+};
+
+template<template<class, class> class T, class U1, class U2, class V>
+struct ptr_traits_rebind_to<T<U1, U2>, V> {
+ typedef T<V, U2> type;
+};
+
+template<template<class, class, class> class T,
+ class U1, class U2, class U3, class V>
+struct ptr_traits_rebind_to<T<U1, U2, U3>, V> {
+ typedef T<V, U2, U3> type;
+};
+#endif
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+template<class T, class U, bool = ptr_traits_has_rebind<T, U>::value>
+struct ptr_traits_rebind {
+ typedef typename T::template rebind<U> type;
+};
+
+template<class T, class U>
+struct ptr_traits_rebind<T, U, false> {
+ typedef typename ptr_traits_rebind_to<T, U>::type type;
+};
+#else
+template<class T, class U>
+struct ptr_traits_rebind {
+ typedef typename ptr_traits_rebind_to<T, U>::type type;
+};
+#endif
+
+template<class T>
+struct ptr_traits_value {
+ typedef T type;
+};
+
+template<>
+struct ptr_traits_value<void> {
+ typedef struct { } type;
+};
+
+} /* detail */
+
+template<class T>
+struct pointer_traits {
+ typedef T pointer;
+ typedef typename detail::ptr_traits_element<T>::type element_type;
+ typedef typename detail::ptr_traits_difference<T>::type difference_type;
+ template<class U>
+ struct rebind_to {
+ typedef typename detail::ptr_traits_rebind<T, U>::type type;
+ };
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ template<class U>
+ using rebind = typename detail::ptr_traits_rebind<T, U>::type;
+#endif
+ static pointer
+ pointer_to(typename detail::ptr_traits_value<element_type>::type& v) {
+ return pointer::pointer_to(v);
+ }
+ static element_type* to_address(const pointer& v) BOOST_NOEXCEPT {
+ return detail::ptr_traits_address(v.operator->());
+ }
+};
+
+template<class T>
+struct pointer_traits<T*> {
+ typedef T* pointer;
+ typedef T element_type;
+ typedef std::ptrdiff_t difference_type;
+ template<class U>
+ struct rebind_to {
+ typedef U* type;
+ };
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ template<class U>
+ using rebind = U*;
+#endif
+ static T*
+ pointer_to(typename detail::ptr_traits_value<T>::type& v) BOOST_NOEXCEPT {
+ return addressof(v);
+ }
+ static T* to_address(T* v) BOOST_NOEXCEPT {
+ return v;
+ }
+};
+#endif
+
+template<class T>
+inline typename pointer_traits<T>::element_type*
+to_address(const T& v) BOOST_NOEXCEPT
+{
+ return pointer_traits<T>::to_address(v);
+}
+
+template<class T>
+inline T*
+to_address(T* v) BOOST_NOEXCEPT
+{
+ return v;
+}
+
+} /* boost */
+
+#endif
diff --git a/boost/core/ref.hpp b/boost/core/ref.hpp
index 47dc858007..7d768ffc75 100644
--- a/boost/core/ref.hpp
+++ b/boost/core/ref.hpp
@@ -8,8 +8,8 @@
#endif
#include <boost/config.hpp>
-#include <boost/utility/addressof.hpp>
-#include <boost/detail/workaround.hpp>
+#include <boost/config/workaround.hpp>
+#include <boost/core/addressof.hpp>
//
// ref.hpp - ref/cref, useful helper functions
diff --git a/boost/coroutine2/detail/config.hpp b/boost/coroutine2/detail/config.hpp
index 307ee4e78a..e725213a91 100644
--- a/boost/coroutine2/detail/config.hpp
+++ b/boost/coroutine2/detail/config.hpp
@@ -27,12 +27,4 @@
# define BOOST_COROUTINES2_DECL
#endif
-#if ! defined(BOOST_COROUTINES2_SOURCE) && ! defined(BOOST_ALL_NO_LIB) && ! defined(BOOST_COROUTINES2_NO_LIB)
-# define BOOST_LIB_NAME boost_coroutine2
-# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_COROUTINES2_DYN_LINK)
-# define BOOST_DYN_LINK
-# endif
-# include <boost/config/auto_link.hpp>
-#endif
-
#endif // BOOST_COROUTINES2_DETAIL_CONFIG_H
diff --git a/boost/coroutine2/detail/coroutine.hpp b/boost/coroutine2/detail/coroutine.hpp
index 1170590183..c52608b163 100644
--- a/boost/coroutine2/detail/coroutine.hpp
+++ b/boost/coroutine2/detail/coroutine.hpp
@@ -29,26 +29,14 @@ class push_coroutine;
#include <boost/coroutine2/detail/pull_coroutine.hpp>
#include <boost/coroutine2/detail/push_coroutine.hpp>
-#if defined(BOOST_EXECUTION_CONTEXT)
-# if (BOOST_EXECUTION_CONTEXT==1)
-# include <boost/coroutine2/detail/pull_control_block_ecv1.hpp>
-# include <boost/coroutine2/detail/push_control_block_ecv1.hpp>
-# else
-# include <boost/coroutine2/detail/pull_control_block_cc.hpp>
-# include <boost/coroutine2/detail/push_control_block_cc.hpp>
-# endif
-
-# include <boost/coroutine2/detail/pull_coroutine.ipp>
-# include <boost/coroutine2/detail/push_coroutine.ipp>
-
-# if (BOOST_EXECUTION_CONTEXT==1)
-# include <boost/coroutine2/detail/pull_control_block_ecv1.ipp>
-# include <boost/coroutine2/detail/push_control_block_ecv1.ipp>
-# else
-# include <boost/coroutine2/detail/pull_control_block_cc.ipp>
-# include <boost/coroutine2/detail/push_control_block_cc.ipp>
-# endif
-#endif
+#include <boost/coroutine2/detail/pull_control_block_cc.hpp>
+#include <boost/coroutine2/detail/push_control_block_cc.hpp>
+
+#include <boost/coroutine2/detail/pull_coroutine.ipp>
+#include <boost/coroutine2/detail/push_coroutine.ipp>
+
+#include <boost/coroutine2/detail/pull_control_block_cc.ipp>
+#include <boost/coroutine2/detail/push_control_block_cc.ipp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
diff --git a/boost/coroutine2/detail/pull_control_block_cc.hpp b/boost/coroutine2/detail/pull_control_block_cc.hpp
index 44a14e2102..5353fb8be1 100644
--- a/boost/coroutine2/detail/pull_control_block_cc.hpp
+++ b/boost/coroutine2/detail/pull_control_block_cc.hpp
@@ -50,7 +50,6 @@ struct pull_coroutine< T >::control_block {
void set( T const&);
void set( T &&);
- void reset();
T & get() noexcept;
@@ -89,7 +88,6 @@ struct pull_coroutine< T & >::control_block {
void resume();
void set( T &);
- void reset();
T & get() noexcept;
diff --git a/boost/coroutine2/detail/pull_control_block_cc.ipp b/boost/coroutine2/detail/pull_control_block_cc.ipp
index 0406202016..486833455e 100644
--- a/boost/coroutine2/detail/pull_control_block_cc.ipp
+++ b/boost/coroutine2/detail/pull_control_block_cc.ipp
@@ -39,7 +39,6 @@ pull_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
cb->~control_block();
// destroy coroutine's stack
cb->state |= state_t::destroy;
- c.resume();
}
template< typename T >
@@ -104,9 +103,6 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
return other->c.resume();
});
#endif
- if ( c.data_available() ) {
- set( c.get_data< T >() );
- }
}
template< typename T >
@@ -140,11 +136,6 @@ template< typename T >
void
pull_coroutine< T >::control_block::resume() {
c = c.resume();
- if ( c.data_available() ) {
- set( c.get_data< T >() );
- } else {
- reset();
- }
if ( except) {
std::rethrow_exception( except);
}
@@ -173,16 +164,6 @@ pull_coroutine< T >::control_block::set( T && t) {
}
template< typename T >
-void
-pull_coroutine< T >::control_block::reset() {
- // destroy data if set
- if ( bvalid) {
- reinterpret_cast< T * >( std::addressof( storage) )->~T();
- }
- bvalid = false;
-}
-
-template< typename T >
T &
pull_coroutine< T >::control_block::get() noexcept {
return * reinterpret_cast< T * >( std::addressof( storage) );
@@ -205,7 +186,6 @@ pull_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
cb->~control_block();
// destroy coroutine's stack
cb->state |= state_t::destroy;
- c.resume();
}
template< typename T >
@@ -270,9 +250,6 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
return other->c.resume();
});
#endif
- if ( c.data_available() ) {
- set( c.get_data< T & >() );
- }
}
template< typename T >
@@ -298,11 +275,6 @@ template< typename T >
void
pull_coroutine< T & >::control_block::resume() {
c = c.resume();
- if ( c.data_available() ) {
- set( c.get_data< T & >() );
- } else {
- reset();
- }
if ( except) {
std::rethrow_exception( except);
}
@@ -316,15 +288,6 @@ pull_coroutine< T & >::control_block::set( T & t) {
}
template< typename T >
-void
-pull_coroutine< T & >::control_block::reset() {
- if ( bvalid) {
- reinterpret_cast< holder * >( std::addressof( storage) )->~holder();
- }
- bvalid = false;
-}
-
-template< typename T >
T &
pull_coroutine< T & >::control_block::get() noexcept {
return reinterpret_cast< holder * >( std::addressof( storage) )->t;
@@ -347,7 +310,6 @@ pull_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
cb->~control_block();
// destroy coroutine's stack
cb->state |= state_t::destroy;
- c.resume();
}
template< typename StackAllocator, typename Fn >
diff --git a/boost/coroutine2/detail/pull_control_block_ecv1.hpp b/boost/coroutine2/detail/pull_control_block_ecv1.hpp
deleted file mode 100644
index 16d65a3e62..0000000000
--- a/boost/coroutine2/detail/pull_control_block_ecv1.hpp
+++ /dev/null
@@ -1,119 +0,0 @@
-
-// Copyright Oliver Kowalke 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_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_HPP
-#define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_HPP
-
-#include <exception>
-#include <functional>
-#include <type_traits>
-
-#include <boost/config.hpp>
-#include <boost/context/execution_context.hpp>
-
-#include <boost/coroutine2/detail/state.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines2 {
-namespace detail {
-
-template< typename T >
-struct pull_coroutine< T >::control_block {
- boost::context::execution_context ctx;
- typename push_coroutine< T >::control_block * other;
- state_t state;
- std::exception_ptr except;
- bool bvalid;
- typename std::aligned_storage< sizeof( T), alignof( T) >::type storage;
-
- static void destroy( control_block * cb) noexcept;
-
- template< typename StackAllocator, typename Fn >
- control_block( context::preallocated, StackAllocator, Fn &&);
-
- control_block( typename push_coroutine< T >::control_block *, boost::context::execution_context const&) noexcept;
-
- ~control_block() noexcept;
-
- control_block( control_block &) = delete;
- control_block & operator=( control_block &) = delete;
-
- void deallocate() noexcept;
-
- void resume();
-
- void set( T *);
-
- T & get() noexcept;
-
- bool valid() const noexcept;
-};
-
-template< typename T >
-struct pull_coroutine< T & >::control_block {
- boost::context::execution_context ctx;
- typename push_coroutine< T & >::control_block * other;
- state_t state;
- std::exception_ptr except;
- T * t;
-
- static void destroy( control_block * cb) noexcept;
-
- template< typename StackAllocator, typename Fn >
- control_block( context::preallocated, StackAllocator, Fn &&);
-
- control_block( typename push_coroutine< T & >::control_block *, boost::context::execution_context const&) noexcept;
-
- ~control_block() noexcept;
-
- control_block( control_block &) = delete;
- control_block & operator=( control_block &) = delete;
-
- void deallocate() noexcept;
-
- void resume();
-
- T & get() noexcept;
-
- bool valid() const noexcept;
-};
-
-struct pull_coroutine< void >::control_block {
- boost::context::execution_context ctx;
- push_coroutine< void >::control_block * other;
- state_t state;
- std::exception_ptr except;
-
- static void destroy( control_block * cb) noexcept;
-
- template< typename StackAllocator, typename Fn >
- control_block( context::preallocated, StackAllocator, Fn &&);
-
- control_block( push_coroutine< void >::control_block *, boost::context::execution_context const&) noexcept;
-
- ~control_block() noexcept;
-
- control_block( control_block &) = delete;
- control_block & operator=( control_block &) = delete;
-
- void deallocate() noexcept;
-
- void resume();
-
- bool valid() const noexcept;
-};
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_HPP
diff --git a/boost/coroutine2/detail/pull_control_block_ecv1.ipp b/boost/coroutine2/detail/pull_control_block_ecv1.ipp
deleted file mode 100644
index 77866041fe..0000000000
--- a/boost/coroutine2/detail/pull_control_block_ecv1.ipp
+++ /dev/null
@@ -1,431 +0,0 @@
-
-// Copyright Oliver Kowalke 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_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
-#define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
-
-#include <exception>
-#include <functional>
-#include <memory>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-
-#include <boost/context/execution_context.hpp>
-
-#include <boost/coroutine2/detail/config.hpp>
-#include <boost/coroutine2/detail/decay_copy.hpp>
-#include <boost/coroutine2/detail/forced_unwind.hpp>
-#include <boost/coroutine2/detail/state.hpp>
-#include <boost/coroutine2/detail/wrap.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines2 {
-namespace detail {
-
-// pull_coroutine< T >
-
-template< typename T >
-void
-pull_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
- boost::context::execution_context ctx = cb->ctx;
- // destroy control structure
- cb->state |= state_t::destroy;
- cb->~control_block();
-}
-
-template< typename T >
-template< typename StackAllocator, typename Fn >
-pull_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
- Fn && fn) :
-#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
- ctx{ std::allocator_arg, palloc, salloc,
- wrap( [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx, void *) mutable noexcept {
- // create synthesized push_coroutine< T >
- typename push_coroutine< T >::control_block synthesized_cb{ this, ctx };
- push_coroutine< T > synthesized{ & synthesized_cb };
- other = & synthesized_cb;
- if ( state_t::none == ( state & state_t::destroy) ) {
- try {
- auto fn = std::move( fn_);
- // call coroutine-fn with synthesized push_coroutine as argument
- fn( synthesized);
- } catch ( forced_unwind const&) {
- // do nothing for unwinding exception
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- other->ctx();
- BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
- },
- std::forward< Fn >( fn),
- boost::context::execution_context::current() ) },
-#else
- ctx{ std::allocator_arg, palloc, salloc,
- [this,fn_=decay_copy( std::forward< Fn >( fn) ),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
- // create synthesized push_coroutine< T >
- typename push_coroutine< T >::control_block synthesized_cb{ this, ctx };
- push_coroutine< T > synthesized{ & synthesized_cb };
- other = & synthesized_cb;
- if ( state_t::none == ( state & state_t::destroy) ) {
- try {
- auto fn = std::move( fn_);
- // call coroutine-fn with synthesized push_coroutine as argument
- fn( synthesized);
- } catch ( forced_unwind const&) {
- // do nothing for unwinding exception
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- other->ctx();
- BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
- }},
-#endif
- other{ nullptr },
- state{ state_t::unwind },
- except{},
- bvalid{ false },
- storage{} {
- // enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
- set( static_cast< T * >( ctx() ) );
-}
-
-template< typename T >
-pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb,
- boost::context::execution_context const& ctx_) noexcept :
- ctx{ ctx_ },
- other{ cb },
- state{ state_t::none },
- except{},
- bvalid{ false },
- storage{} {
-}
-
-template< typename T >
-pull_coroutine< T >::control_block::~control_block() {
- if ( state_t::none == ( state & state_t::complete) &&
- state_t::none != ( state & state_t::unwind) ) {
- // unwind coroutine stack
- other->ctx = boost::context::execution_context::current();
- ctx( context::exec_ontop_arg, unwind_coroutine);
- }
- // destroy data if it set
- if ( bvalid) {
- reinterpret_cast< T * >( std::addressof( storage) )->~T();
- }
-}
-
-template< typename T >
-void
-pull_coroutine< T >::control_block::deallocate() noexcept {
- if ( state_t::none != ( state & state_t::unwind) ) {
- destroy( this);
- }
-}
-
-template< typename T >
-void
-pull_coroutine< T >::control_block::resume() {
- other->ctx = boost::context::execution_context::current();
- set( static_cast< T * >( ctx() ) );
- if ( except) {
- std::rethrow_exception( except);
- }
-}
-
-template< typename T >
-void
-pull_coroutine< T >::control_block::set( T * t) {
- // destroy data if it set
- if ( bvalid) {
- reinterpret_cast< T * >( std::addressof( storage) )->~T();
- }
- if ( nullptr != t) {
- ::new ( static_cast< void * >( std::addressof( storage) ) ) T( std::move( * t) );
- bvalid = true;
- } else {
- bvalid = false;
- }
-}
-
-template< typename T >
-T &
-pull_coroutine< T >::control_block::get() noexcept {
- return * reinterpret_cast< T * >( std::addressof( storage) );
-}
-
-template< typename T >
-bool
-pull_coroutine< T >::control_block::valid() const noexcept {
- return nullptr != other && state_t::none == ( state & state_t::complete) && bvalid;
-}
-
-
-// pull_coroutine< T & >
-
-template< typename T >
-void
-pull_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
- boost::context::execution_context ctx = cb->ctx;
- // destroy control structure
- cb->state |= state_t::destroy;
- cb->~control_block();
-}
-
-template< typename T >
-template< typename StackAllocator, typename Fn >
-pull_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
- Fn && fn) :
-#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
- ctx{ std::allocator_arg, palloc, salloc,
- wrap( [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx, void *) mutable noexcept {
- // create synthesized push_coroutine< T >
- typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx };
- push_coroutine< T & > synthesized{ & synthesized_cb };
- other = & synthesized_cb;
- if ( state_t::none == ( state & state_t::destroy) ) {
- try {
- auto fn = std::move( fn_);
- // call coroutine-fn with synthesized push_coroutine as argument
- fn( synthesized);
- } catch ( forced_unwind const&) {
- // do nothing for unwinding exception
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- other->ctx();
- BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
- },
- std::forward< Fn >( fn),
- boost::context::execution_context::current() ) },
-#else
- ctx{ std::allocator_arg, palloc, salloc,
- [this,fn_=decay_copy( std::forward< Fn >( fn) ),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
- // create synthesized push_coroutine< T >
- typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx };
- push_coroutine< T & > synthesized{ & synthesized_cb };
- other = & synthesized_cb;
- if ( state_t::none == ( state & state_t::destroy) ) {
- try {
- auto fn = std::move( fn_);
- // call coroutine-fn with synthesized push_coroutine as argument
- fn( synthesized);
- } catch ( forced_unwind const&) {
- // do nothing for unwinding exception
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- other->ctx();
- BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
- }},
-#endif
- other{ nullptr },
- state{ state_t::unwind },
- except{},
- t{ nullptr } {
- // enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
- t = static_cast< T * >( ctx() );
-}
-
-template< typename T >
-pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb,
- boost::context::execution_context const& ctx_) noexcept :
- ctx{ ctx_ },
- other{ cb },
- state{ state_t::none },
- except{},
- t( nullptr) {
-}
-
-template< typename T >
-pull_coroutine< T & >::control_block::~control_block() {
- if ( state_t::none == ( state & state_t::complete) &&
- state_t::none != ( state & state_t::unwind) ) {
- // unwind coroutine stack
- other->ctx = boost::context::execution_context::current();
- ctx( context::exec_ontop_arg, unwind_coroutine);
- }
-}
-
-template< typename T >
-void
-pull_coroutine< T & >::control_block::deallocate() noexcept {
- if ( state_t::none != ( state & state_t::unwind) ) {
- destroy( this);
- }
-}
-
-template< typename T >
-void
-pull_coroutine< T & >::control_block::resume() {
- other->ctx = boost::context::execution_context::current();
- t = static_cast< T * >( ctx() );
- if ( except) {
- std::rethrow_exception( except);
- }
-}
-
-template< typename T >
-T &
-pull_coroutine< T & >::control_block::get() noexcept {
- return * static_cast< T * >( t);
-}
-
-template< typename T >
-bool
-pull_coroutine< T & >::control_block::valid() const noexcept {
- return nullptr != other && state_t::none == ( state & state_t::complete) && nullptr != t;
-}
-
-
-// pull_coroutine< void >
-
-inline
-void
-pull_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
- boost::context::execution_context ctx = cb->ctx;
- // destroy control structure
- cb->state |= state_t::destroy;
- cb->~control_block();
-}
-
-template< typename StackAllocator, typename Fn >
-pull_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
- Fn && fn) :
-#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
- ctx{ std::allocator_arg, palloc, salloc,
- wrap( [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx, void *) mutable noexcept {
- // create synthesized push_coroutine< T >
- typename push_coroutine< void >::control_block synthesized_cb{ this, ctx };
- push_coroutine< void > synthesized{ & synthesized_cb };
- other = & synthesized_cb;
- if ( state_t::none == ( state & state_t::destroy) ) {
- try {
- auto fn = std::move( fn_);
- // call coroutine-fn with synthesized push_coroutine as argument
- fn( synthesized);
- } catch ( forced_unwind const&) {
- // do nothing for unwinding exception
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- other->ctx();
- BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
- },
- std::forward< Fn >( fn),
- boost::context::execution_context::current() ) },
-#else
- ctx{ std::allocator_arg, palloc, salloc,
- [this,fn_=decay_copy( std::forward< Fn >( fn) ),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
- // create synthesized push_coroutine< T >
- typename push_coroutine< void >::control_block synthesized_cb{ this, ctx };
- push_coroutine< void > synthesized{ & synthesized_cb };
- other = & synthesized_cb;
- if ( state_t::none == ( state & state_t::destroy) ) {
- try {
- auto fn = std::move( fn_);
- // call coroutine-fn with synthesized push_coroutine as argument
- fn( synthesized);
- } catch ( forced_unwind const&) {
- // do nothing for unwinding exception
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- other->ctx();
- BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
- }},
-#endif
- other{ nullptr },
- state{ state_t::unwind },
- except{} {
- // enter coroutine-fn in order to have first value available after ctor returns
- ctx();
-}
-
-inline
-pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb,
- boost::context::execution_context const& ctx_) noexcept :
- ctx{ ctx_ },
- other{ cb },
- state{ state_t::none },
- except{} {
-}
-
-inline
-pull_coroutine< void >::control_block::~control_block() {
- if ( state_t::none == ( state & state_t::complete) &&
- state_t::none != ( state & state_t::unwind) ) {
- // unwind coroutine stack
- other->ctx = boost::context::execution_context::current();
- ctx( context::exec_ontop_arg, unwind_coroutine);
- }
-}
-
-inline
-void
-pull_coroutine< void >::control_block::deallocate() noexcept {
- if ( state_t::none != ( state & state_t::unwind) ) {
- destroy( this);
- }
-}
-
-inline
-void
-pull_coroutine< void >::control_block::resume() {
- other->ctx = boost::context::execution_context::current();
- ctx();
- if ( except) {
- std::rethrow_exception( except);
- }
-}
-
-inline
-bool
-pull_coroutine< void >::control_block::valid() const noexcept {
- return nullptr != other && state_t::none == ( state & state_t::complete);
-}
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
diff --git a/boost/coroutine2/detail/push_control_block_cc.ipp b/boost/coroutine2/detail/push_control_block_cc.ipp
index 9972c7039f..98b24f2642 100644
--- a/boost/coroutine2/detail/push_control_block_cc.ipp
+++ b/boost/coroutine2/detail/push_control_block_cc.ipp
@@ -38,7 +38,6 @@ push_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
cb->~control_block();
// destroy coroutine's stack
cb->state |= state_t::destroy;
- c.resume();
}
template< typename T >
@@ -58,12 +57,6 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
pull_coroutine< T > synthesized{ & synthesized_cb };
other = & synthesized_cb;
other->c = other->c.resume();
- // set transferred value
- if ( other->c.data_available() ) {
- synthesized_cb.set( other->c.template get_data< T >() );
- } else {
- synthesized_cb.reset();
- }
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
@@ -91,12 +84,6 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
pull_coroutine< T > synthesized{ & synthesized_cb };
other = & synthesized_cb;
other->c = other->c.resume();
- // set transferred value
- if ( other->c.data_available() ) {
- synthesized_cb.set( other->c.template get_data< T >() );
- } else {
- synthesized_cb.reset();
- }
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
@@ -137,8 +124,10 @@ push_coroutine< T >::control_block::deallocate() noexcept {
template< typename T >
void
push_coroutine< T >::control_block::resume( T const& data) {
- // pass an pointer to other context
- c = c.resume( data);
+ // pass data to other context
+ other->set( data);
+ // resume other context
+ c = c.resume();
if ( except) {
std::rethrow_exception( except);
}
@@ -147,8 +136,10 @@ push_coroutine< T >::control_block::resume( T const& data) {
template< typename T >
void
push_coroutine< T >::control_block::resume( T && data) {
- // pass an pointer to other context
- c = c.resume( std::move( data) );
+ // pass data to other context
+ other->set( std::move( data) );
+ // resume other context
+ c = c.resume();
if ( except) {
std::rethrow_exception( except);
}
@@ -171,7 +162,6 @@ push_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
cb->~control_block();
// destroy coroutine's stack
cb->state |= state_t::destroy;
- c.resume();
}
template< typename T >
@@ -191,12 +181,6 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
pull_coroutine< T & > synthesized{ & synthesized_cb };
other = & synthesized_cb;
other->c = other->c.resume();
- // set transferred value
- if ( other->c.data_available() ) {
- synthesized_cb.set( other->c.template get_data< T & >() );
- } else {
- synthesized_cb.reset();
- }
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
@@ -224,12 +208,6 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
pull_coroutine< T & > synthesized{ & synthesized_cb };
other = & synthesized_cb;
other->c = other->c.resume();
- // set transferred value
- if ( other->c.data_available() ) {
- synthesized_cb.set( other->c.template get_data< T & >() );
- } else {
- synthesized_cb.reset();
- }
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
@@ -269,9 +247,11 @@ push_coroutine< T & >::control_block::deallocate() noexcept {
template< typename T >
void
-push_coroutine< T & >::control_block::resume( T & t) {
- // pass an pointer to other context
- c = c.resume( std::ref( t) );
+push_coroutine< T & >::control_block::resume( T & data) {
+ // pass data to other context
+ other->set( data);
+ // resume other context
+ c = c.resume();
if ( except) {
std::rethrow_exception( except);
}
@@ -294,7 +274,6 @@ push_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
cb->~control_block();
// destroy coroutine's stack
cb->state |= state_t::destroy;
- c.resume();
}
template< typename StackAllocator, typename Fn >
diff --git a/boost/coroutine2/detail/push_control_block_ecv1.hpp b/boost/coroutine2/detail/push_control_block_ecv1.hpp
deleted file mode 100644
index 29d49716a7..0000000000
--- a/boost/coroutine2/detail/push_control_block_ecv1.hpp
+++ /dev/null
@@ -1,111 +0,0 @@
-
-// Copyright Oliver Kowalke 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_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_HPP
-#define BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_HPP
-
-#include <functional>
-#include <exception>
-
-#include <boost/config.hpp>
-#include <boost/context/execution_context.hpp>
-
-#include <boost/coroutine2/detail/state.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines2 {
-namespace detail {
-
-template< typename T >
-struct push_coroutine< T >::control_block {
- boost::context::execution_context ctx;
- typename pull_coroutine< T >::control_block * other;
- state_t state;
- std::exception_ptr except;
-
- static void destroy( control_block * cb) noexcept;
-
- template< typename StackAllocator, typename Fn >
- control_block( context::preallocated, StackAllocator, Fn &&);
-
- control_block( typename pull_coroutine< T >::control_block *, boost::context::execution_context const&) noexcept;
-
- ~control_block() noexcept;
-
- control_block( control_block &) = delete;
- control_block & operator=( control_block &) = delete;
-
- void deallocate() noexcept;
-
- void resume( T const&);
-
- void resume( T &&);
-
- bool valid() const noexcept;
-};
-
-template< typename T >
-struct push_coroutine< T & >::control_block {
- boost::context::execution_context ctx;
- typename pull_coroutine< T & >::control_block * other;
- state_t state;
- std::exception_ptr except;
-
- static void destroy( control_block * cb) noexcept;
-
- template< typename StackAllocator, typename Fn >
- control_block( context::preallocated, StackAllocator, Fn &&);
-
- control_block( typename pull_coroutine< T & >::control_block *, boost::context::execution_context const&) noexcept;
-
- ~control_block() noexcept;
-
- control_block( control_block &) = delete;
- control_block & operator=( control_block &) = delete;
-
- void deallocate() noexcept;
-
- void resume( T &);
-
- bool valid() const noexcept;
-};
-
-struct push_coroutine< void >::control_block {
- boost::context::execution_context ctx;
- pull_coroutine< void >::control_block * other;
- state_t state;
- std::exception_ptr except;
-
- static void destroy( control_block * cb) noexcept;
-
- template< typename StackAllocator, typename Fn >
- control_block( context::preallocated, StackAllocator, Fn &&);
-
- control_block( pull_coroutine< void >::control_block *, boost::context::execution_context const&) noexcept;
-
- ~control_block() noexcept;
-
- control_block( control_block &) = delete;
- control_block & operator=( control_block &) = delete;
-
- void deallocate() noexcept;
-
- void resume();
-
- bool valid() const noexcept;
-};
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_HPP
diff --git a/boost/coroutine2/detail/push_control_block_ecv1.ipp b/boost/coroutine2/detail/push_control_block_ecv1.ipp
deleted file mode 100644
index 8b4ae3fb04..0000000000
--- a/boost/coroutine2/detail/push_control_block_ecv1.ipp
+++ /dev/null
@@ -1,428 +0,0 @@
-
-// Copyright Oliver Kowalke 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_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
-#define BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
-
-#include <algorithm>
-#include <exception>
-#include <functional>
-#include <memory>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-
-#include <boost/context/execution_context.hpp>
-
-#include <boost/coroutine2/detail/config.hpp>
-#include <boost/coroutine2/detail/decay_copy.hpp>
-#include <boost/coroutine2/detail/forced_unwind.hpp>
-#include <boost/coroutine2/detail/state.hpp>
-#include <boost/coroutine2/detail/wrap.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines2 {
-namespace detail {
-
-// push_coroutine< T >
-
-template< typename T >
-void
-push_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
- boost::context::execution_context ctx = cb->ctx;
- // destroy control structure
- cb->state |= state_t::destroy;
- cb->~control_block();
-}
-
-template< typename T >
-template< typename StackAllocator, typename Fn >
-push_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
- Fn && fn) :
-#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
- ctx{ std::allocator_arg, palloc, salloc,
- wrap( [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx, void * vp) mutable noexcept {
- // create synthesized pull_coroutine< T >
- typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
- pull_coroutine< T > synthesized{ & synthesized_cb };
- other = & synthesized_cb;
- if ( state_t::none == ( state & state_t::destroy) ) {
- try {
- // jump back to ctor
- T * t = static_cast< T * >( ctx() );
- // set transferred value
- synthesized_cb.set( t);
- auto fn = std::move( fn_);
- // call coroutine-fn with synthesized pull_coroutine as argument
- fn( synthesized);
- } catch ( forced_unwind const&) {
- // do nothing for unwinding exception
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- other->ctx();
- BOOST_ASSERT_MSG( false, "push_coroutine is complete");
- },
- std::forward< Fn >( fn),
- boost::context::execution_context::current() ) },
-#else
- ctx{ std::allocator_arg, palloc, salloc,
- [this,fn_=decay_copy( std::forward< Fn >( fn) ),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
- // create synthesized pull_coroutine< T >
- typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
- pull_coroutine< T > synthesized{ & synthesized_cb };
- other = & synthesized_cb;
- if ( state_t::none == ( state & state_t::destroy) ) {
- try {
- // jump back to ctor
- T * t = static_cast< T * >( ctx() );
- // set transferred value
- synthesized_cb.set( t);
- auto fn = std::move( fn_);
- // call coroutine-fn with synthesized pull_coroutine as argument
- fn( synthesized);
- } catch ( forced_unwind const&) {
- // do nothing for unwinding exception
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- other->ctx();
- BOOST_ASSERT_MSG( false, "push_coroutine is complete");
- }},
-#endif
- other{ nullptr },
- state{ state_t::unwind },
- except{} {
- // enter coroutine-fn in order to get other set
- ctx();
-}
-
-template< typename T >
-push_coroutine< T >::control_block::control_block( typename pull_coroutine< T >::control_block * cb,
- boost::context::execution_context const& ctx_) noexcept :
- ctx{ ctx_ },
- other{ cb },
- state{ state_t::none },
- except{} {
-}
-
-template< typename T >
-push_coroutine< T >::control_block::~control_block() {
- if ( state_t::none == ( state & state_t::complete) &&
- state_t::none != ( state & state_t::unwind) ) {
- // unwind coroutine stack
- other->ctx = boost::context::execution_context::current();
- ctx( context::exec_ontop_arg, unwind_coroutine);
- }
-}
-
-template< typename T >
-void
-push_coroutine< T >::control_block::deallocate() noexcept {
- if ( state_t::none != ( state & state_t::unwind) ) {
- destroy( this);
- }
-}
-
-template< typename T >
-void
-push_coroutine< T >::control_block::resume( T const& t) {
- other->ctx = boost::context::execution_context::current();
- // pass an pointer to other context
- ctx( const_cast< T * >( & t) );
- if ( except) {
- std::rethrow_exception( except);
- }
-}
-
-template< typename T >
-void
-push_coroutine< T >::control_block::resume( T && t) {
- other->ctx = boost::context::execution_context::current();
- // pass an pointer to other context
- ctx( std::addressof( t) );
- if ( except) {
- std::rethrow_exception( except);
- }
-}
-
-template< typename T >
-bool
-push_coroutine< T >::control_block::valid() const noexcept {
- return state_t::none == ( state & state_t::complete );
-}
-
-
-// push_coroutine< T & >
-
-template< typename T >
-void
-push_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
- boost::context::execution_context ctx = cb->ctx;
- // destroy control structure
- cb->state |= state_t::destroy;
- cb->~control_block();
-}
-
-template< typename T >
-template< typename StackAllocator, typename Fn >
-push_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
- Fn && fn) :
-#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
- ctx{ std::allocator_arg, palloc, salloc,
- wrap( [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx, void * vp) mutable noexcept {
- // create synthesized pull_coroutine< T >
- typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
- pull_coroutine< T & > synthesized{ & synthesized_cb };
- other = & synthesized_cb;
- if ( state_t::none == ( state & state_t::destroy) ) {
- try {
- // jump back to ctor
- T * t = static_cast< T * >( ctx() );
- // set transferred value
- synthesized_cb.t = t;
- auto fn = std::move( fn_);
- // call coroutine-fn with synthesized pull_coroutine as argument
- fn( synthesized);
- } catch ( forced_unwind const&) {
- // do nothing for unwinding exception
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- other->ctx();
- BOOST_ASSERT_MSG( false, "push_coroutine is complete");
- },
- std::forward< Fn >( fn),
- boost::context::execution_context::current() ) },
-#else
- ctx{ std::allocator_arg, palloc, salloc,
- [this,fn_=decay_copy( std::forward< Fn >( fn) ),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
- // create synthesized pull_coroutine< T >
- typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
- pull_coroutine< T & > synthesized{ & synthesized_cb };
- other = & synthesized_cb;
- if ( state_t::none == ( state & state_t::destroy) ) {
- try {
- // jump back to ctor
- T * t = static_cast< T * >( ctx() );
- // set transferred value
- synthesized_cb.t = t;
- auto fn = std::move( fn_);
- // call coroutine-fn with synthesized pull_coroutine as argument
- fn( synthesized);
- } catch ( forced_unwind const&) {
- // do nothing for unwinding exception
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- other->ctx();
- BOOST_ASSERT_MSG( false, "push_coroutine is complete");
- }},
-#endif
- other{ nullptr },
- state{ state_t::unwind },
- except{} {
- // enter coroutine-fn in order to get other set
- ctx();
-}
-
-template< typename T >
-push_coroutine< T & >::control_block::control_block( typename pull_coroutine< T & >::control_block * cb,
- boost::context::execution_context const& ctx_) noexcept :
- ctx{ ctx_ },
- other{ cb },
- state{ state_t::none },
- except{} {
-}
-
-template< typename T >
-push_coroutine< T & >::control_block::~control_block() {
- if ( state_t::none == ( state & state_t::complete) &&
- state_t::none != ( state & state_t::unwind) ) {
- // unwind coroutine stack
- other->ctx = boost::context::execution_context::current();
- ctx( context::exec_ontop_arg, unwind_coroutine);
- }
-}
-
-template< typename T >
-void
-push_coroutine< T & >::control_block::deallocate() noexcept {
- if ( state_t::none != ( state & state_t::unwind) ) {
- destroy( this);
- }
-}
-
-template< typename T >
-void
-push_coroutine< T & >::control_block::resume( T & t) {
- other->ctx = boost::context::execution_context::current();
- // pass an pointer to other context
- ctx( const_cast< typename std::remove_const< T >::type * >( std::addressof( t) ) );
- if ( except) {
- std::rethrow_exception( except);
- }
-}
-
-template< typename T >
-bool
-push_coroutine< T & >::control_block::valid() const noexcept {
- return state_t::none == ( state & state_t::complete );
-}
-
-
-// push_coroutine< void >
-
-inline
-void
-push_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
- boost::context::execution_context ctx = cb->ctx;
- // destroy control structure
- cb->state |= state_t::destroy;
- cb->~control_block();
-}
-
-template< typename StackAllocator, typename Fn >
-push_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc, Fn && fn) :
-#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
- ctx{ std::allocator_arg, palloc, salloc,
- wrap( [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx,
- void * vp) mutable noexcept {
- // create synthesized pull_coroutine< T >
- typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx };
- pull_coroutine< void > synthesized{ & synthesized_cb };
- other = & synthesized_cb;
- if ( state_t::none == ( state & state_t::destroy) ) {
- try {
- // jump back to ctor
- ctx();
- auto fn = std::move( fn_);
- // call coroutine-fn with synthesized pull_coroutine as argument
- fn( synthesized);
- } catch ( forced_unwind const&) {
- // do nothing for unwinding exception
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- other->ctx();
- BOOST_ASSERT_MSG( false, "push_coroutine is complete");
- },
- std::forward< Fn >( fn),
- boost::context::execution_context::current() ) },
-#else
- ctx{ std::allocator_arg, palloc, salloc,
- [this,fn_=decay_copy( std::forward< Fn >( fn) ),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
- // create synthesized pull_coroutine< T >
- typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx };
- pull_coroutine< void > synthesized{ & synthesized_cb };
- other = & synthesized_cb;
- if ( state_t::none == ( state & state_t::destroy) ) {
- try {
- // jump back to ctor
- ctx();
- auto fn = std::move( fn_);
- // call coroutine-fn with synthesized pull_coroutine as argument
- fn( synthesized);
- } catch ( forced_unwind const&) {
- // do nothing for unwinding exception
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- other->ctx();
- BOOST_ASSERT_MSG( false, "push_coroutine is complete");
- }},
-#endif
- other{ nullptr },
- state{ state_t::unwind },
- except{} {
- // enter coroutine-fn in order to get other set
- ctx();
-}
-
-inline
-push_coroutine< void >::control_block::control_block( pull_coroutine< void >::control_block * cb,
- boost::context::execution_context const& ctx_) noexcept :
- ctx{ ctx_ },
- other{ cb },
- state{ state_t::none },
- except{} {
-}
-
-inline
-push_coroutine< void >::control_block::~control_block() {
- if ( state_t::none == ( state & state_t::complete) &&
- state_t::none != ( state & state_t::unwind) ) {
- // unwind coroutine stack
- other->ctx = boost::context::execution_context::current();
- ctx( context::exec_ontop_arg, unwind_coroutine);
- }
-}
-
-inline
-void
-push_coroutine< void >::control_block::deallocate() noexcept {
- if ( state_t::none != ( state & state_t::unwind) ) {
- destroy( this);
- }
-}
-
-inline
-void
-push_coroutine< void >::control_block::resume() {
- other->ctx = boost::context::execution_context::current();
- ctx();
- if ( except) {
- std::rethrow_exception( except);
- }
-}
-
-inline
-bool
-push_coroutine< void >::control_block::valid() const noexcept {
- return state_t::none == ( state & state_t::complete );
-}
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
diff --git a/boost/coroutine2/detail/wrap.hpp b/boost/coroutine2/detail/wrap.hpp
index 25abce3b61..cd56338484 100644
--- a/boost/coroutine2/detail/wrap.hpp
+++ b/boost/coroutine2/detail/wrap.hpp
@@ -11,14 +11,9 @@
#include <boost/config.hpp>
#include <boost/context/detail/invoke.hpp>
-#if (BOOST_EXECUTION_CONTEXT==1)
-# include <boost/context/execution_context.hpp>
-#else
-# include <boost/context/continuation.hpp>
-#endif
+#include <boost/context/continuation.hpp>
-#include <boost/fiber/detail/config.hpp>
-#include <boost/fiber/detail/data.hpp>
+#include <boost/coroutine2/detail/config.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
@@ -28,45 +23,6 @@ namespace boost {
namespace coroutines2 {
namespace detail {
-#if (BOOST_EXECUTION_CONTEXT==1)
-template< typename Fn1, typename Fn2 >
-class wrapper {
-private:
- typename std::decay< Fn1 >::type fn1_;
- typename std::decay< Fn2 >::type fn2_;
- boost::context::execution_context ctx_;
-
-public:
- wrapper( Fn1 && fn1, Fn2 && fn2,
- boost::context::execution_context const& ctx) :
- fn1_( std::move( fn1) ),
- fn2_( std::move( fn2) ),
- ctx_{ ctx } {
- }
-
- wrapper( wrapper const&) = delete;
- wrapper & operator=( wrapper const&) = delete;
-
- wrapper( wrapper && other) = default;
- wrapper & operator=( wrapper && other) = default;
-
- void operator()( void * vp) {
- boost::context::detail::invoke(
- std::move( fn1_),
- fn2_, ctx_, vp);
- }
-};
-
-template< typename Fn1, typename Fn2 >
-wrapper< Fn1, Fn2 >
-wrap( Fn1 && fn1, Fn2 && fn2,
- boost::context::execution_context const& ctx) {
- return wrapper< Fn1, Fn2 >(
- std::forward< Fn1 >( fn1),
- std::forward< Fn2 >( fn2),
- ctx);
-}
-#else
template< typename Fn1, typename Fn2 >
class wrapper {
private:
@@ -101,7 +57,6 @@ wrap( Fn1 && fn1, Fn2 && fn2) {
std::forward< Fn1 >( fn1),
std::forward< Fn2 >( fn2) );
}
-#endif
}}}
diff --git a/boost/cstdint.hpp b/boost/cstdint.hpp
index bf7097ec8c..31b67417ae 100644
--- a/boost/cstdint.hpp
+++ b/boost/cstdint.hpp
@@ -374,7 +374,7 @@ namespace boost
|| (defined(_XOPEN_UNIX) && (_XOPEN_UNIX+0 > 0) && !defined(__UCLIBC__)) \
|| defined(__CYGWIN__) \
|| defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) \
- || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(sun)
+ || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || (defined(sun) && !defined(BOOST_HAS_STDINT_H)) || defined(INTPTR_MAX)
namespace boost {
using ::intptr_t;
@@ -422,6 +422,20 @@ INT#_C macros if they're not already defined (John Maddock).
#if defined(__GNUC__) && (__GNUC__ >= 4)
#pragma GCC system_header
#endif
+//
+// Undef the macros as a precaution, since we may get here if <stdint.h> has failed
+// to define them all, see https://svn.boost.org/trac/boost/ticket/12786
+//
+#undef INT8_C
+#undef INT16_C
+#undef INT32_C
+#undef INT64_C
+#undef INTMAX_C
+#undef UINT8_C
+#undef UINT16_C
+#undef UINT32_C
+#undef UINT64_C
+#undef UINTMAX_C
#include <limits.h>
# define BOOST__STDC_CONSTANT_MACROS_DEFINED
diff --git a/boost/date_time/dst_rules.hpp b/boost/date_time/dst_rules.hpp
index 32290190d9..73a98996d8 100644
--- a/boost/date_time/dst_rules.hpp
+++ b/boost/date_time/dst_rules.hpp
@@ -106,12 +106,12 @@ namespace boost {
const time_duration_type& dst_end_offset,
const time_duration_type& dst_length_minutes)
{
- unsigned int start_minutes =
- dst_start_offset.hours() * 60 + dst_start_offset.minutes();
- unsigned int end_minutes =
- dst_end_offset.hours() * 60 + dst_end_offset.minutes();
- long length_minutes =
- dst_length_minutes.hours() * 60 + dst_length_minutes.minutes();
+ unsigned int start_minutes = static_cast<unsigned>(
+ dst_start_offset.hours() * 60 + dst_start_offset.minutes());
+ unsigned int end_minutes = static_cast<unsigned>(
+ dst_end_offset.hours() * 60 + dst_end_offset.minutes());
+ long length_minutes = static_cast<long>(
+ dst_length_minutes.hours() * 60 + dst_length_minutes.minutes());
return local_is_dst(current_day, time_of_day,
dst_start_day, start_minutes,
diff --git a/boost/date_time/locale_config.hpp b/boost/date_time/locale_config.hpp
index 42a2b73043..26a928f7bc 100644
--- a/boost/date_time/locale_config.hpp
+++ b/boost/date_time/locale_config.hpp
@@ -22,7 +22,9 @@
//This file basically becomes a noop if locales are not properly supported
#if (defined(BOOST_NO_STD_LOCALE) \
|| (BOOST_WORKAROUND( BOOST_MSVC, < 1300)) \
- || (BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x581 )) ) )
+ || (BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x581 )) ) \
+ || (BOOST_WORKAROUND( BOOST_XLCPP_ZOS, BOOST_TESTED_AT( 0x42010000 )) ) /* <cctype> "shadows" the locale enabled overloads from <locale> */ \
+ )
#define BOOST_DATE_TIME_NO_LOCALE
#endif
diff --git a/boost/date_time/posix_time/conversion.hpp b/boost/date_time/posix_time/conversion.hpp
index ed3d4867e9..42a9894af7 100644
--- a/boost/date_time/posix_time/conversion.hpp
+++ b/boost/date_time/posix_time/conversion.hpp
@@ -10,6 +10,7 @@
*/
#include <cstring>
+#include <boost/cstdint.hpp>
#include <boost/date_time/posix_time/ptime.hpp>
#include <boost/date_time/posix_time/posix_time_duration.hpp>
#include <boost/date_time/filetime_functions.hpp>
@@ -21,21 +22,18 @@ namespace boost {
namespace posix_time {
-
//! Function that converts a time_t into a ptime.
inline
ptime from_time_t(std::time_t t)
{
- ptime start(gregorian::date(1970,1,1));
- return start + seconds(static_cast<long>(t));
+ return ptime(gregorian::date(1970,1,1)) + seconds(static_cast<long>(t));
}
//! Function that converts a ptime into a time_t
inline
std::time_t to_time_t(ptime pt)
{
- time_duration dur = pt - ptime(gregorian::date(1970,1,1));
- return std::time_t(dur.total_seconds());
+ return (pt - ptime(gregorian::date(1970,1,1))).total_seconds();
}
//! Convert a time to a tm structure truncating any fractional seconds
@@ -43,9 +41,9 @@ namespace posix_time {
std::tm to_tm(const boost::posix_time::ptime& t) {
std::tm timetm = boost::gregorian::to_tm(t.date());
boost::posix_time::time_duration td = t.time_of_day();
- timetm.tm_hour = td.hours();
- timetm.tm_min = td.minutes();
- timetm.tm_sec = td.seconds();
+ timetm.tm_hour = static_cast<int>(td.hours());
+ timetm.tm_min = static_cast<int>(td.minutes());
+ timetm.tm_sec = static_cast<int>(td.seconds());
timetm.tm_isdst = -1; // -1 used when dst info is unknown
return timetm;
}
@@ -54,9 +52,9 @@ namespace posix_time {
std::tm to_tm(const boost::posix_time::time_duration& td) {
std::tm timetm;
std::memset(&timetm, 0, sizeof(timetm));
- timetm.tm_hour = date_time::absolute_value(td.hours());
- timetm.tm_min = date_time::absolute_value(td.minutes());
- timetm.tm_sec = date_time::absolute_value(td.seconds());
+ timetm.tm_hour = static_cast<int>(date_time::absolute_value(td.hours()));
+ timetm.tm_min = static_cast<int>(date_time::absolute_value(td.minutes()));
+ timetm.tm_sec = static_cast<int>(date_time::absolute_value(td.seconds()));
timetm.tm_isdst = -1; // -1 used when dst info is unknown
return timetm;
}
diff --git a/boost/date_time/time_resolution_traits.hpp b/boost/date_time/time_resolution_traits.hpp
index 3b6134cf1c..7ba42c20b5 100644
--- a/boost/date_time/time_resolution_traits.hpp
+++ b/boost/date_time/time_resolution_traits.hpp
@@ -9,7 +9,7 @@
* $Date$
*/
-
+#include <ctime>
#include <boost/cstdint.hpp>
#include <boost/date_time/time_defs.hpp>
#include <boost/date_time/int_adapter.hpp>
@@ -68,7 +68,7 @@ namespace date_time {
typename frac_sec_type::int_type resolution_adjust,
#endif
unsigned short frac_digits,
- typename var_type = boost::int32_t >
+ typename var_type = std::time_t >
class time_resolution_traits {
public:
typedef typename frac_sec_type::int_type fractional_seconds_type;
@@ -120,14 +120,14 @@ namespace date_time {
minutes = absolute_value(minutes);
seconds = absolute_value(seconds);
fs = absolute_value(fs);
- return (((((fractional_seconds_type(hours)*3600)
- + (fractional_seconds_type(minutes)*60)
- + seconds)*res_adjust()) + fs) * -1);
+ return static_cast<tick_type>(((((fractional_seconds_type(hours)*3600)
+ + (fractional_seconds_type(minutes)*60)
+ + seconds)*res_adjust()) + fs) * -1);
}
- return (((fractional_seconds_type(hours)*3600)
- + (fractional_seconds_type(minutes)*60)
- + seconds)*res_adjust()) + fs;
+ return static_cast<tick_type>((((fractional_seconds_type(hours)*3600)
+ + (fractional_seconds_type(minutes)*60)
+ + seconds)*res_adjust()) + fs);
}
};
diff --git a/boost/detail/winapi/debugapi.hpp b/boost/detail/winapi/debugapi.hpp
new file mode 100644
index 0000000000..188345c823
--- /dev/null
+++ b/boost/detail/winapi/debugapi.hpp
@@ -0,0 +1,79 @@
+// debugapi.hpp --------------------------------------------------------------
+//
+// Copyright 2017 Vinnie Falco
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+
+#ifndef BOOST_DETAIL_WINAPI_DEBUGAPI_HPP
+#define BOOST_DETAIL_WINAPI_DEBUGAPI_HPP
+
+#include <boost/detail/winapi/basic_types.hpp>
+#include <boost/detail/winapi/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if !defined( BOOST_USE_WINDOWS_H )
+extern "C" {
+
+#if (BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_NT4)
+
+BOOST_SYMBOL_IMPORT
+boost::detail::winapi::BOOL_
+WINAPI
+IsDebuggerPresent(
+ BOOST_DETAIL_WINAPI_VOID
+ );
+
+#endif
+
+BOOST_SYMBOL_IMPORT
+boost::detail::winapi::VOID_
+WINAPI
+OutputDebugStringA(
+ boost::detail::winapi::LPCSTR_
+ );
+
+BOOST_SYMBOL_IMPORT
+boost::detail::winapi::VOID_
+WINAPI
+OutputDebugStringW(
+ boost::detail::winapi::LPCWSTR_
+ );
+
+}
+#endif // extern "C"
+
+namespace boost {
+namespace detail {
+namespace winapi {
+
+#if (BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_NT4)
+using ::IsDebuggerPresent;
+#endif
+
+using ::OutputDebugStringA;
+using ::OutputDebugStringW;
+
+inline
+void
+output_debug_string(char const* s)
+{
+ ::OutputDebugStringA(s);
+}
+
+inline
+void
+output_debug_string(wchar_t const* s)
+{
+ ::OutputDebugStringW(s);
+}
+
+}
+}
+}
+
+#endif // BOOST_DETAIL_WINAPI_DEBUGAPI_HPP
diff --git a/boost/detail/winapi/file_management.hpp b/boost/detail/winapi/file_management.hpp
index 80567bd477..b90b7ee07b 100644
--- a/boost/detail/winapi/file_management.hpp
+++ b/boost/detail/winapi/file_management.hpp
@@ -242,6 +242,24 @@ const DWORD_ FILE_END_ = 2;
#endif // defined( BOOST_USE_WINDOWS_H )
+// Some of these constants are not defined by Windows SDK in MinGW or older MSVC
+const DWORD_ FILE_FLAG_WRITE_THROUGH_ = 0x80000000;
+const DWORD_ FILE_FLAG_OVERLAPPED_ = 0x40000000;
+const DWORD_ FILE_FLAG_NO_BUFFERING_ = 0x20000000;
+const DWORD_ FILE_FLAG_RANDOM_ACCESS_ = 0x10000000;
+const DWORD_ FILE_FLAG_SEQUENTIAL_SCAN_ = 0x08000000;
+const DWORD_ FILE_FLAG_DELETE_ON_CLOSE_ = 0x04000000;
+const DWORD_ FILE_FLAG_BACKUP_SEMANTICS_ = 0x02000000;
+const DWORD_ FILE_FLAG_POSIX_SEMANTICS_ = 0x01000000;
+const DWORD_ FILE_FLAG_SESSION_AWARE_ = 0x00800000;
+const DWORD_ FILE_FLAG_OPEN_REPARSE_POINT_ = 0x00200000;
+const DWORD_ FILE_FLAG_OPEN_NO_RECALL_ = 0x00100000;
+const DWORD_ FILE_FLAG_FIRST_PIPE_INSTANCE_ = 0x00080000;
+
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN8
+const DWORD_ FILE_FLAG_OPEN_REQUIRING_OPLOCK_ = 0x00040000;
+#endif
+
// This constant is not defined in Windows SDK up until 6.0A
const DWORD_ FILE_ATTRIBUTE_VIRTUAL_ = 0x00010000;
diff --git a/boost/detail/winapi/jobs.hpp b/boost/detail/winapi/jobs.hpp
index 63087a2b2a..3c3bf0872b 100644
--- a/boost/detail/winapi/jobs.hpp
+++ b/boost/detail/winapi/jobs.hpp
@@ -37,22 +37,30 @@ BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI IsProcessInJob(
BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI TerminateJobObject(
boost::detail::winapi::HANDLE_ hJob,
boost::detail::winapi::UINT_ uExitCode);
+} // extern "C"
+#endif // !defined( BOOST_USE_WINDOWS_H )
+// MinGW does not declare OpenJobObjectA/W in headers but exports them from libraries
+#if !defined( BOOST_USE_WINDOWS_H ) || defined( BOOST_WINAPI_IS_MINGW )
+extern "C" {
+#if !defined( BOOST_NO_ANSI_APIS )
BOOST_SYMBOL_IMPORT boost::detail::winapi::HANDLE_ WINAPI OpenJobObjectA(
boost::detail::winapi::DWORD_ dwDesiredAccess,
boost::detail::winapi::BOOL_ bInheritHandles,
boost::detail::winapi::LPCSTR_ lpName);
+#endif
BOOST_SYMBOL_IMPORT boost::detail::winapi::HANDLE_ WINAPI OpenJobObjectW(
boost::detail::winapi::DWORD_ dwDesiredAccess,
boost::detail::winapi::BOOL_ bInheritHandles,
boost::detail::winapi::LPCWSTR_ lpName);
} // extern "C"
-#endif // !defined( BOOST_USE_WINDOWS_H )
+#endif // !defined( BOOST_USE_WINDOWS_H ) || defined( BOOST_WINAPI_IS_MINGW )
namespace boost { namespace detail { namespace winapi {
-#if defined( BOOST_USE_WINDOWS_H )
+// MinGW does not define job constants
+#if defined( BOOST_USE_WINDOWS_H ) && !defined( BOOST_WINAPI_IS_MINGW )
const DWORD_ JOB_OBJECT_ASSIGN_PROCESS_ = JOB_OBJECT_ASSIGN_PROCESS;
const DWORD_ JOB_OBJECT_SET_ATTRIBUTES_ = JOB_OBJECT_SET_ATTRIBUTES;
const DWORD_ JOB_OBJECT_QUERY_ = JOB_OBJECT_QUERY;
@@ -109,7 +117,7 @@ BOOST_FORCEINLINE HANDLE_ create_job_object(LPSECURITY_ATTRIBUTES_ lpJobAttribut
BOOST_FORCEINLINE HANDLE_ open_job_object(DWORD_ dwDesiredAccess, BOOL_ bInheritHandles, LPCWSTR_ lpName)
{
- return OpenJobObjectW(dwDesiredAccess, bInheritHandles, lpName);
+ return ::OpenJobObjectW(dwDesiredAccess, bInheritHandles, lpName);
}
} // namespace winapi
diff --git a/boost/detail/winapi/stack_backtrace.hpp b/boost/detail/winapi/stack_backtrace.hpp
new file mode 100644
index 0000000000..637be6cdf4
--- /dev/null
+++ b/boost/detail/winapi/stack_backtrace.hpp
@@ -0,0 +1,55 @@
+// stack_backtrace.hpp --------------------------------------------------------------
+//
+// Copyright 2017 Andrey Semashev
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_DETAIL_WINAPI_STACK_BACKTRACE_HPP_INCLUDED_
+#define BOOST_DETAIL_WINAPI_STACK_BACKTRACE_HPP_INCLUDED_
+
+#include <boost/detail/winapi/basic_types.hpp>
+#include <boost/detail/winapi/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+// MinGW does not provide RtlCaptureStackBackTrace
+#if !defined( BOOST_WINAPI_IS_MINGW )
+
+// Note: RtlCaptureStackBackTrace is available in WinXP SP1 and later, but we don't discriminate SP versions
+#if (BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WINXP)
+
+// Windows SDK shipped with MSVC 7.1 and 8 does not declare RtlCaptureStackBackTrace in headers but allows to link with it
+#if !defined( BOOST_USE_WINDOWS_H ) || (defined(_MSC_VER) && (_MSC_VER+0) < 1500)
+extern "C" {
+
+BOOST_SYMBOL_IMPORT
+boost::detail::winapi::WORD_
+NTAPI
+RtlCaptureStackBackTrace(
+ boost::detail::winapi::DWORD_ FramesToSkip,
+ boost::detail::winapi::DWORD_ FramesToCapture,
+ boost::detail::winapi::PVOID_* BackTrace,
+ boost::detail::winapi::PDWORD_ BackTraceHash
+ );
+
+} // extern "C"
+#endif
+
+namespace boost {
+namespace detail {
+namespace winapi {
+
+using ::RtlCaptureStackBackTrace;
+
+}
+}
+}
+
+#endif // (BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WINXP)
+
+#endif // !defined( BOOST_WINAPI_IS_MINGW )
+
+#endif // BOOST_DETAIL_WINAPI_STACK_BACKTRACE_HPP_INCLUDED_
diff --git a/boost/detail/workaround.hpp b/boost/detail/workaround.hpp
index 7727aaf1de..fb96115880 100644
--- a/boost/detail/workaround.hpp
+++ b/boost/detail/workaround.hpp
@@ -3,270 +3,8 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef WORKAROUND_DWA2002126_HPP
-# define WORKAROUND_DWA2002126_HPP
+#define WORKAROUND_DWA2002126_HPP
-// Compiler/library version workaround macro
-//
-// Usage:
-//
-// #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
-// // workaround for eVC4 and VC6
-// ... // workaround code here
-// #endif
-//
-// When BOOST_STRICT_CONFIG is defined, expands to 0. Otherwise, the
-// first argument must be undefined or expand to a numeric
-// value. The above expands to:
-//
-// (BOOST_MSVC) != 0 && (BOOST_MSVC) < 1300
-//
-// When used for workarounds that apply to the latest known version
-// and all earlier versions of a compiler, the following convention
-// should be observed:
-//
-// #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1301))
-//
-// The version number in this case corresponds to the last version in
-// which the workaround was known to have been required. When
-// BOOST_DETECT_OUTDATED_WORKAROUNDS is not the defined, the macro
-// BOOST_TESTED_AT(x) expands to "!= 0", which effectively activates
-// the workaround for any version of the compiler. When
-// BOOST_DETECT_OUTDATED_WORKAROUNDS is defined, a compiler warning or
-// error will be issued if the compiler version exceeds the argument
-// to BOOST_TESTED_AT(). This can be used to locate workarounds which
-// may be obsoleted by newer versions.
-
-# ifndef BOOST_STRICT_CONFIG
-
-#include <boost/config.hpp>
-
-#ifndef __BORLANDC__
-#define __BORLANDC___WORKAROUND_GUARD 1
-#else
-#define __BORLANDC___WORKAROUND_GUARD 0
-#endif
-#ifndef __CODEGEARC__
-#define __CODEGEARC___WORKAROUND_GUARD 1
-#else
-#define __CODEGEARC___WORKAROUND_GUARD 0
-#endif
-#ifndef _MSC_VER
-#define _MSC_VER_WORKAROUND_GUARD 1
-#else
-#define _MSC_VER_WORKAROUND_GUARD 0
-#endif
-#ifndef _MSC_FULL_VER
-#define _MSC_FULL_VER_WORKAROUND_GUARD 1
-#else
-#define _MSC_FULL_VER_WORKAROUND_GUARD 0
-#endif
-#ifndef BOOST_MSVC
-#define BOOST_MSVC_WORKAROUND_GUARD 1
-#else
-#define BOOST_MSVC_WORKAROUND_GUARD 0
-#endif
-#ifndef BOOST_MSVC_FULL_VER
-#define BOOST_MSVC_FULL_VER_WORKAROUND_GUARD 1
-#else
-#define BOOST_MSVC_FULL_VER_WORKAROUND_GUARD 0
-#endif
-#ifndef __GNUC__
-#define __GNUC___WORKAROUND_GUARD 1
-#else
-#define __GNUC___WORKAROUND_GUARD 0
-#endif
-#ifndef __GNUC_MINOR__
-#define __GNUC_MINOR___WORKAROUND_GUARD 1
-#else
-#define __GNUC_MINOR___WORKAROUND_GUARD 0
-#endif
-#ifndef __GNUC_PATCHLEVEL__
-#define __GNUC_PATCHLEVEL___WORKAROUND_GUARD 1
-#else
-#define __GNUC_PATCHLEVEL___WORKAROUND_GUARD 0
-#endif
-#ifndef BOOST_GCC
-#define BOOST_GCC_WORKAROUND_GUARD 1
-#else
-#define BOOST_GCC_WORKAROUND_GUARD 0
-#endif
-#ifndef __IBMCPP__
-#define __IBMCPP___WORKAROUND_GUARD 1
-#else
-#define __IBMCPP___WORKAROUND_GUARD 0
-#endif
-#ifndef __SUNPRO_CC
-#define __SUNPRO_CC_WORKAROUND_GUARD 1
-#else
-#define __SUNPRO_CC_WORKAROUND_GUARD 0
-#endif
-#ifndef __DECCXX_VER
-#define __DECCXX_VER_WORKAROUND_GUARD 1
-#else
-#define __DECCXX_VER_WORKAROUND_GUARD 0
-#endif
-#ifndef __MWERKS__
-#define __MWERKS___WORKAROUND_GUARD 1
-#else
-#define __MWERKS___WORKAROUND_GUARD 0
-#endif
-#ifndef __EDG__
-#define __EDG___WORKAROUND_GUARD 1
-#else
-#define __EDG___WORKAROUND_GUARD 0
-#endif
-#ifndef __EDG_VERSION__
-#define __EDG_VERSION___WORKAROUND_GUARD 1
-#else
-#define __EDG_VERSION___WORKAROUND_GUARD 0
-#endif
-#ifndef __HP_aCC
-#define __HP_aCC_WORKAROUND_GUARD 1
-#else
-#define __HP_aCC_WORKAROUND_GUARD 0
-#endif
-#ifndef __hpxstd98
-#define __hpxstd98_WORKAROUND_GUARD 1
-#else
-#define __hpxstd98_WORKAROUND_GUARD 0
-#endif
-#ifndef _CRAYC
-#define _CRAYC_WORKAROUND_GUARD 1
-#else
-#define _CRAYC_WORKAROUND_GUARD 0
-#endif
-#ifndef __DMC__
-#define __DMC___WORKAROUND_GUARD 1
-#else
-#define __DMC___WORKAROUND_GUARD 0
-#endif
-#ifndef MPW_CPLUS
-#define MPW_CPLUS_WORKAROUND_GUARD 1
-#else
-#define MPW_CPLUS_WORKAROUND_GUARD 0
-#endif
-#ifndef __COMO__
-#define __COMO___WORKAROUND_GUARD 1
-#else
-#define __COMO___WORKAROUND_GUARD 0
-#endif
-#ifndef __COMO_VERSION__
-#define __COMO_VERSION___WORKAROUND_GUARD 1
-#else
-#define __COMO_VERSION___WORKAROUND_GUARD 0
-#endif
-#ifndef __INTEL_COMPILER
-#define __INTEL_COMPILER_WORKAROUND_GUARD 1
-#else
-#define __INTEL_COMPILER_WORKAROUND_GUARD 0
-#endif
-#ifndef __ICL
-#define __ICL_WORKAROUND_GUARD 1
-#else
-#define __ICL_WORKAROUND_GUARD 0
-#endif
-#ifndef _COMPILER_VERSION
-#define _COMPILER_VERSION_WORKAROUND_GUARD 1
-#else
-#define _COMPILER_VERSION_WORKAROUND_GUARD 0
-#endif
-
-#ifndef _RWSTD_VER
-#define _RWSTD_VER_WORKAROUND_GUARD 1
-#else
-#define _RWSTD_VER_WORKAROUND_GUARD 0
-#endif
-#ifndef BOOST_RWSTD_VER
-#define BOOST_RWSTD_VER_WORKAROUND_GUARD 1
-#else
-#define BOOST_RWSTD_VER_WORKAROUND_GUARD 0
-#endif
-#ifndef __GLIBCPP__
-#define __GLIBCPP___WORKAROUND_GUARD 1
-#else
-#define __GLIBCPP___WORKAROUND_GUARD 0
-#endif
-#ifndef _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC
-#define _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC_WORKAROUND_GUARD 1
-#else
-#define _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC_WORKAROUND_GUARD 0
-#endif
-#ifndef __SGI_STL_PORT
-#define __SGI_STL_PORT_WORKAROUND_GUARD 1
-#else
-#define __SGI_STL_PORT_WORKAROUND_GUARD 0
-#endif
-#ifndef _STLPORT_VERSION
-#define _STLPORT_VERSION_WORKAROUND_GUARD 1
-#else
-#define _STLPORT_VERSION_WORKAROUND_GUARD 0
-#endif
-#ifndef __LIBCOMO_VERSION__
-#define __LIBCOMO_VERSION___WORKAROUND_GUARD 1
-#else
-#define __LIBCOMO_VERSION___WORKAROUND_GUARD 0
-#endif
-#ifndef _CPPLIB_VER
-#define _CPPLIB_VER_WORKAROUND_GUARD 1
-#else
-#define _CPPLIB_VER_WORKAROUND_GUARD 0
-#endif
-
-#ifndef BOOST_INTEL_CXX_VERSION
-#define BOOST_INTEL_CXX_VERSION_WORKAROUND_GUARD 1
-#else
-#define BOOST_INTEL_CXX_VERSION_WORKAROUND_GUARD 0
-#endif
-#ifndef BOOST_INTEL_WIN
-#define BOOST_INTEL_WIN_WORKAROUND_GUARD 1
-#else
-#define BOOST_INTEL_WIN_WORKAROUND_GUARD 0
-#endif
-#ifndef BOOST_DINKUMWARE_STDLIB
-#define BOOST_DINKUMWARE_STDLIB_WORKAROUND_GUARD 1
-#else
-#define BOOST_DINKUMWARE_STDLIB_WORKAROUND_GUARD 0
-#endif
-#ifndef BOOST_INTEL
-#define BOOST_INTEL_WORKAROUND_GUARD 1
-#else
-#define BOOST_INTEL_WORKAROUND_GUARD 0
-#endif
-// Always define to zero, if it's used it'll be defined my MPL:
-#define BOOST_MPL_CFG_GCC_WORKAROUND_GUARD 0
-
-# define BOOST_WORKAROUND(symbol, test) \
- ((symbol ## _WORKAROUND_GUARD + 0 == 0) && \
- (symbol != 0) && (1 % (( (symbol test) ) + 1)))
-// ^ ^ ^ ^
-// The extra level of parenthesis nesting above, along with the
-// BOOST_OPEN_PAREN indirection below, is required to satisfy the
-// broken preprocessor in MWCW 8.3 and earlier.
-//
-// The basic mechanism works as follows:
-// (symbol test) + 1 => if (symbol test) then 2 else 1
-// 1 % ((symbol test) + 1) => if (symbol test) then 1 else 0
-//
-// The complication with % is for cooperation with BOOST_TESTED_AT().
-// When "test" is BOOST_TESTED_AT(x) and
-// BOOST_DETECT_OUTDATED_WORKAROUNDS is #defined,
-//
-// symbol test => if (symbol <= x) then 1 else -1
-// (symbol test) + 1 => if (symbol <= x) then 2 else 0
-// 1 % ((symbol test) + 1) => if (symbol <= x) then 1 else divide-by-zero
-//
-
-# ifdef BOOST_DETECT_OUTDATED_WORKAROUNDS
-# define BOOST_OPEN_PAREN (
-# define BOOST_TESTED_AT(value) > value) ?(-1): BOOST_OPEN_PAREN 1
-# else
-# define BOOST_TESTED_AT(value) != ((value)-(value))
-# endif
-
-# else
-
-# define BOOST_WORKAROUND(symbol, test) 0
-
-# endif
+#include <boost/config/workaround.hpp>
#endif // WORKAROUND_DWA2002126_HPP
diff --git a/boost/dll/detail/pe_info.hpp b/boost/dll/detail/pe_info.hpp
index 341a12323b..72668a075f 100644
--- a/boost/dll/detail/pe_info.hpp
+++ b/boost/dll/detail/pe_info.hpp
@@ -14,6 +14,7 @@
# pragma once
#endif
+#include <boost/cstdint.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/dll/detail/x_info_interface.hpp>
@@ -29,9 +30,9 @@ namespace boost { namespace dll { namespace detail {
// because that header must be included only on Windows platform
typedef unsigned char BYTE_;
typedef unsigned short WORD_;
-typedef unsigned long DWORD_;
-typedef long LONG_;
-typedef unsigned long ULONG_;
+typedef boost::uint32_t DWORD_;
+typedef boost::int32_t LONG_;
+typedef boost::uint32_t ULONG_;
typedef boost::int64_t LONGLONG_;
typedef boost::uint64_t ULONGLONG_;
diff --git a/boost/dynamic_bitset/dynamic_bitset.hpp b/boost/dynamic_bitset/dynamic_bitset.hpp
index 05798b5262..c1ae8b15f1 100644
--- a/boost/dynamic_bitset/dynamic_bitset.hpp
+++ b/boost/dynamic_bitset/dynamic_bitset.hpp
@@ -86,7 +86,7 @@ public:
// the one and only non-copy ctor
- reference(block_type & b, block_type pos)
+ reference(block_type & b, block_width_type pos)
:m_block(b),
m_mask( (assert(pos < bits_per_block),
block_type(1) << pos )
@@ -328,6 +328,10 @@ public:
friend bool operator<(const dynamic_bitset<B, A>& a,
const dynamic_bitset<B, A>& b);
+ template <typename B, typename A>
+ friend bool oplessthan(const dynamic_bitset<B, A>& a,
+ const dynamic_bitset<B, A>& b);
+
template <typename B, typename A, typename BlockOutputIterator>
friend void to_block_range(const dynamic_bitset<B, A>& b,
@@ -1420,23 +1424,95 @@ template <typename Block, typename Allocator>
bool operator<(const dynamic_bitset<Block, Allocator>& a,
const dynamic_bitset<Block, Allocator>& b)
{
- assert(a.size() == b.size());
- typedef typename dynamic_bitset<Block, Allocator>::size_type size_type;
+// assert(a.size() == b.size());
- //if (a.size() == 0)
- // return false;
+ typedef BOOST_DEDUCED_TYPENAME dynamic_bitset<Block, Allocator>::size_type size_type;
+
+ size_type asize(a.size());
+ size_type bsize(b.size());
- // Since we are storing the most significant bit
- // at pos == size() - 1, we need to do the comparisons in reverse.
- //
- for (size_type ii = a.num_blocks(); ii > 0; --ii) {
- size_type i = ii-1;
- if (a.m_bits[i] < b.m_bits[i])
+ if (!bsize)
+ {
+ return false;
+ }
+ else if (!asize)
+ {
return true;
- else if (a.m_bits[i] > b.m_bits[i])
+ }
+ else if (asize == bsize)
+ {
+ for (size_type ii = a.num_blocks(); ii > 0; --ii)
+ {
+ size_type i = ii-1;
+ if (a.m_bits[i] < b.m_bits[i])
+ return true;
+ else if (a.m_bits[i] > b.m_bits[i])
+ return false;
+ }
return false;
- }
- return false;
+ }
+ else
+ {
+
+ size_type leqsize(std::min BOOST_PREVENT_MACRO_SUBSTITUTION(asize,bsize));
+
+ for (size_type ii = 0; ii < leqsize; ++ii,--asize,--bsize)
+ {
+ size_type i = asize-1;
+ size_type j = bsize-1;
+ if (a[i] < b[j])
+ return true;
+ else if (a[i] > b[j])
+ return false;
+ }
+ return (a.size() < b.size());
+ }
+}
+
+template <typename Block, typename Allocator>
+bool oplessthan(const dynamic_bitset<Block, Allocator>& a,
+ const dynamic_bitset<Block, Allocator>& b)
+{
+// assert(a.size() == b.size());
+
+ typedef BOOST_DEDUCED_TYPENAME dynamic_bitset<Block, Allocator>::size_type size_type;
+
+ size_type asize(a.num_blocks());
+ size_type bsize(b.num_blocks());
+ assert(asize == 3);
+ assert(bsize == 4);
+
+ if (!bsize)
+ {
+ return false;
+ }
+ else if (!asize)
+ {
+ return true;
+ }
+ else
+ {
+
+ size_type leqsize(std::min BOOST_PREVENT_MACRO_SUBSTITUTION(asize,bsize));
+ assert(leqsize == 3);
+
+ //if (a.size() == 0)
+ // return false;
+
+ // Since we are storing the most significant bit
+ // at pos == size() - 1, we need to do the comparisons in reverse.
+ //
+ for (size_type ii = 0; ii < leqsize; ++ii,--asize,--bsize)
+ {
+ size_type i = asize-1;
+ size_type j = bsize-1;
+ if (a.m_bits[i] < b.m_bits[j])
+ return true;
+ else if (a.m_bits[i] > b.m_bits[j])
+ return false;
+ }
+ return (a.num_blocks() < b.num_blocks());
+ }
}
template <typename Block, typename Allocator>
diff --git a/boost/enable_shared_from_this.hpp b/boost/enable_shared_from_this.hpp
index b1bb63d9a2..18b938d5d0 100644
--- a/boost/enable_shared_from_this.hpp
+++ b/boost/enable_shared_from_this.hpp
@@ -10,7 +10,7 @@
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
-// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
//
#include <boost/smart_ptr/enable_shared_from_this.hpp>
diff --git a/boost/exception/N3757.hpp b/boost/exception/N3757.hpp
deleted file mode 100644
index 23b06066b1..0000000000
--- a/boost/exception/N3757.hpp
+++ /dev/null
@@ -1,46 +0,0 @@
-//Copyright (c) 2006-2013 Emil Dotchevski and Reverge Studios, Inc.
-
-//Distributed under the 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 UUID_9011016A11A711E3B46CD9FA6088709B
-#define UUID_9011016A11A711E3B46CD9FA6088709B
-#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
-#pragma GCC system_header
-#endif
-#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
-#pragma warning(push,1)
-#endif
-
-#include <boost/exception/info.hpp>
-#include <boost/exception/get_error_info.hpp>
-
-namespace
-boost
- {
- //Here we're using the boost::error_info machinery to store the info in the exception
- //object. Within the context of N3757, this is strictly an implementation detail.
-
- template <class Tag>
- inline
- void
- exception::
- set( typename Tag::type const & v )
- {
- exception_detail::set_info(*this,error_info<Tag,typename Tag::type>(v));
- }
-
- template <class Tag>
- inline
- typename Tag::type const *
- exception::
- get() const
- {
- return get_error_info<error_info<Tag,typename Tag::type> >(*this);
- }
- }
-
-#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
-#pragma warning(pop)
-#endif
-#endif
diff --git a/boost/exception/all.hpp b/boost/exception/all.hpp
index 32eb15051f..58b02d00c1 100644
--- a/boost/exception/all.hpp
+++ b/boost/exception/all.hpp
@@ -5,13 +5,8 @@
#ifndef UUID_316FDA946C0D11DEA9CBAE5255D89593
#define UUID_316FDA946C0D11DEA9CBAE5255D89593
-#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
-#pragma GCC system_header
-#endif
-#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
-#pragma warning(push,1)
-#endif
+#include <boost/config.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <boost/exception/error_info.hpp>
#include <boost/exception/exception.hpp>
@@ -29,8 +24,4 @@
#include <boost/exception/errinfo_nested_exception.hpp>
#include <boost/exception_ptr.hpp>
#endif
-
-#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
-#pragma warning(pop)
-#endif
#endif
diff --git a/boost/exception/detail/error_info_impl.hpp b/boost/exception/detail/error_info_impl.hpp
index ecd086dd87..6c48d61ab3 100644
--- a/boost/exception/detail/error_info_impl.hpp
+++ b/boost/exception/detail/error_info_impl.hpp
@@ -5,6 +5,14 @@
#ifndef UUID_CE6983AC753411DDA764247956D89593
#define UUID_CE6983AC753411DDA764247956D89593
+
+#include <boost/config.hpp>
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+#include <boost/type_traits/is_nothrow_move_constructible.hpp>
+#endif
+#include <utility>
+#include <string>
+
#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
#pragma GCC system_header
#endif
@@ -12,10 +20,6 @@
#pragma warning(push,1)
#endif
-#include <boost/config.hpp>
-#include <utility>
-#include <string>
-
namespace
boost
{
@@ -28,8 +32,7 @@ boost
public:
virtual std::string name_value_string() const = 0;
-
- protected:
+ virtual error_info_base * clone() const = 0;
virtual
~error_info_base() throw()
@@ -43,39 +46,53 @@ boost
error_info:
public exception_detail::error_info_base
{
+ error_info_base *
+ clone() const
+ {
+ return new error_info<Tag,T>(*this);
+ }
public:
-
typedef T value_type;
-
- error_info( value_type const & value );
+ error_info( value_type const & v ):
+ v_(v)
+ {
+ }
+#if (__GNUC__*100+__GNUC_MINOR__!=406) //workaround for g++ bug
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- error_info( error_info const & );
- error_info( value_type && value ) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(value_type(std::move(value))));
- error_info( error_info && x ) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(value_type(std::move(x.value_))));
+ error_info( error_info const & x ):
+ v_(x.v_)
+ {
+ }
+ error_info( T && v ) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<T>::value):
+ v_(std::move(v))
+ {
+ }
+ error_info( error_info && x ) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<T>::value):
+ v_(std::move(x.v_))
+ {
+ }
#endif
- ~error_info() throw();
-
+#endif
+ ~error_info() throw()
+ {
+ }
value_type const &
value() const
{
- return value_;
+ return v_;
}
-
value_type &
value()
{
- return value_;
+ return v_;
}
-
private:
error_info & operator=( error_info const & );
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
error_info & operator=( error_info && x );
#endif
-
std::string name_value_string() const;
-
- value_type value_;
+ value_type v_;
};
}
diff --git a/boost/exception/detail/exception_ptr.hpp b/boost/exception/detail/exception_ptr.hpp
index cac64e6ab3..8e19f0d9df 100644
--- a/boost/exception/detail/exception_ptr.hpp
+++ b/boost/exception/detail/exception_ptr.hpp
@@ -5,12 +5,6 @@
#ifndef UUID_618474C2DE1511DEB74A388C56D89593
#define UUID_618474C2DE1511DEB74A388C56D89593
-#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
-#pragma GCC system_header
-#endif
-#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
-#pragma warning(push,1)
-#endif
#include <boost/config.hpp>
#ifdef BOOST_NO_EXCEPTIONS
@@ -19,8 +13,8 @@
#include <boost/exception/exception.hpp>
#include <boost/exception/info.hpp>
#include <boost/exception/diagnostic_information.hpp>
-#include <boost/exception/detail/type_info.hpp>
#include <boost/exception/detail/clone_current_exception.hpp>
+#include <boost/exception/detail/type_info.hpp>
#ifndef BOOST_NO_RTTI
#include <boost/core/demangle.hpp>
#endif
@@ -30,6 +24,13 @@
#include <ios>
#include <stdlib.h>
+#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
+#pragma GCC system_header
+#endif
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
+#pragma warning(push,1)
+#endif
+
namespace
boost
{
@@ -394,7 +395,7 @@ boost
{
return exception_detail::current_exception_std_exception(e);
}
-#ifndef BOOST_NO_TYPEID
+ #ifndef BOOST_NO_TYPEID
catch(
std::bad_cast & e )
{
@@ -405,7 +406,7 @@ boost
{
return exception_detail::current_exception_std_exception(e);
}
-#endif
+ #endif
catch(
std::bad_exception & e )
{
diff --git a/boost/exception/detail/is_output_streamable.hpp b/boost/exception/detail/is_output_streamable.hpp
index 847f3484b8..10e5c5163e 100644
--- a/boost/exception/detail/is_output_streamable.hpp
+++ b/boost/exception/detail/is_output_streamable.hpp
@@ -5,6 +5,9 @@
#ifndef UUID_898984B4076411DD973EDFA055D89593
#define UUID_898984B4076411DD973EDFA055D89593
+
+#include <ostream>
+
#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
#pragma GCC system_header
#endif
@@ -12,8 +15,6 @@
#pragma warning(push,1)
#endif
-#include <ostream>
-
namespace
boost
{
diff --git a/boost/exception/detail/object_hex_dump.hpp b/boost/exception/detail/object_hex_dump.hpp
index 53c8bf6f36..267bf0bf3e 100644
--- a/boost/exception/detail/object_hex_dump.hpp
+++ b/boost/exception/detail/object_hex_dump.hpp
@@ -5,12 +5,6 @@
#ifndef UUID_6F463AC838DF11DDA3E6909F56D89593
#define UUID_6F463AC838DF11DDA3E6909F56D89593
-#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
-#pragma GCC system_header
-#endif
-#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
-#pragma warning(push,1)
-#endif
#include <boost/exception/detail/type_info.hpp>
#include <iomanip>
@@ -19,6 +13,13 @@
#include <sstream>
#include <cstdlib>
+#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
+#pragma GCC system_header
+#endif
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
+#pragma warning(push,1)
+#endif
+
namespace
boost
{
diff --git a/boost/exception/detail/type_info.hpp b/boost/exception/detail/type_info.hpp
index b8c7d48bae..739ac5748e 100644
--- a/boost/exception/detail/type_info.hpp
+++ b/boost/exception/detail/type_info.hpp
@@ -5,6 +5,13 @@
#ifndef UUID_C3E1741C754311DDB2834CCA55D89593
#define UUID_C3E1741C754311DDB2834CCA55D89593
+
+#include <boost/config.hpp>
+#include <boost/core/typeinfo.hpp>
+#include <boost/core/demangle.hpp>
+#include <boost/current_function.hpp>
+#include <string>
+
#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
#pragma GCC system_header
#endif
@@ -12,12 +19,6 @@
#pragma warning(push,1)
#endif
-#include <boost/core/typeinfo.hpp>
-#include <boost/core/demangle.hpp>
-#include <boost/current_function.hpp>
-#include <boost/config.hpp>
-#include <string>
-
namespace
boost
{
diff --git a/boost/exception/diagnostic_information.hpp b/boost/exception/diagnostic_information.hpp
index 305e8edd61..48f06a0fb9 100644
--- a/boost/exception/diagnostic_information.hpp
+++ b/boost/exception/diagnostic_information.hpp
@@ -5,12 +5,6 @@
#ifndef UUID_0552D49838DD11DD90146B8956D89593
#define UUID_0552D49838DD11DD90146B8956D89593
-#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
-#pragma GCC system_header
-#endif
-#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
-#pragma warning(push,1)
-#endif
#include <boost/config.hpp>
#include <boost/exception/get_error_info.hpp>
@@ -22,9 +16,18 @@
#include <exception>
#include <sstream>
#include <string>
-
#ifndef BOOST_NO_EXCEPTIONS
#include <boost/exception/current_exception_cast.hpp>
+#endif
+
+#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
+#pragma GCC system_header
+#endif
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
+#pragma warning(push,1)
+#endif
+
+#ifndef BOOST_NO_EXCEPTIONS
namespace
boost
{
diff --git a/boost/exception/enable_current_exception.hpp b/boost/exception/enable_current_exception.hpp
index 988105378c..495cc90a59 100644
--- a/boost/exception/enable_current_exception.hpp
+++ b/boost/exception/enable_current_exception.hpp
@@ -3,4 +3,9 @@
//Distributed under the 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 UUID_851700A4F7CF11E6B2EE06DD14915323
+#define UUID_851700A4F7CF11E6B2EE06DD14915323
+
#include <boost/exception/exception.hpp>
+
+#endif
diff --git a/boost/exception/enable_error_info.hpp b/boost/exception/enable_error_info.hpp
index 988105378c..202217af66 100644
--- a/boost/exception/enable_error_info.hpp
+++ b/boost/exception/enable_error_info.hpp
@@ -3,4 +3,9 @@
//Distributed under the 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 UUID_A0F7404AF7CF11E6908227DD14915323
+#define UUID_A0F7404AF7CF11E6908227DD14915323
+
#include <boost/exception/exception.hpp>
+
+#endif
diff --git a/boost/exception/errinfo_errno.hpp b/boost/exception/errinfo_errno.hpp
index de44e17155..ebd8f25fbc 100644
--- a/boost/exception/errinfo_errno.hpp
+++ b/boost/exception/errinfo_errno.hpp
@@ -5,6 +5,11 @@
#ifndef UUID_F0EE17BE6C1211DE87FF459155D89593
#define UUID_F0EE17BE6C1211DE87FF459155D89593
+
+#include <boost/exception/info.hpp>
+#include <errno.h>
+#include <string.h>
+
#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
#pragma GCC system_header
#endif
@@ -13,10 +18,6 @@
#pragma warning(disable:4996)
#endif
-#include <boost/exception/info.hpp>
-#include <errno.h>
-#include <string.h>
-
namespace
boost
{
diff --git a/boost/exception/get_error_info.hpp b/boost/exception/get_error_info.hpp
index 51a21ba899..831717df59 100644
--- a/boost/exception/get_error_info.hpp
+++ b/boost/exception/get_error_info.hpp
@@ -5,19 +5,21 @@
#ifndef UUID_1A590226753311DD9E4CCF6156D89593
#define UUID_1A590226753311DD9E4CCF6156D89593
-#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
-#pragma GCC system_header
-#endif
-#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
-#pragma warning(push,1)
-#endif
+#include <boost/config.hpp>
#include <boost/exception/exception.hpp>
#include <boost/exception/detail/error_info_impl.hpp>
#include <boost/exception/detail/type_info.hpp>
#include <boost/exception/detail/shared_ptr.hpp>
#include <boost/assert.hpp>
+#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
+#pragma GCC system_header
+#endif
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
+#pragma warning(push,1)
+#endif
+
namespace
boost
{
diff --git a/boost/exception/info.hpp b/boost/exception/info.hpp
index f06df42aaf..f7ac50ecfc 100644
--- a/boost/exception/info.hpp
+++ b/boost/exception/info.hpp
@@ -5,20 +5,21 @@
#ifndef UUID_8D22C4CA9CC811DCAA9133D256D89593
#define UUID_8D22C4CA9CC811DCAA9133D256D89593
-#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
-#pragma GCC system_header
-#endif
-#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
-#pragma warning(push,1)
-#endif
+#include <boost/config.hpp>
#include <boost/exception/exception.hpp>
#include <boost/exception/to_string_stub.hpp>
#include <boost/exception/detail/error_info_impl.hpp>
#include <boost/exception/detail/shared_ptr.hpp>
-#include <boost/config.hpp>
#include <map>
+#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
+#pragma GCC system_header
+#endif
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
+#pragma warning(push,1)
+#endif
+
namespace
boost
{
@@ -40,45 +41,6 @@ boost
template <class Tag,class T>
inline
- error_info<Tag,T>::
- error_info( value_type const & value ):
- value_(value)
- {
- }
-
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- template <class Tag,class T>
- inline
- error_info<Tag,T>::
- error_info( error_info const & x ):
- value_(x.value_)
- {
- }
- template <class Tag,class T>
- inline
- error_info<Tag,T>::
- error_info( value_type && value ) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(value_type(std::move(value)))):
- value_(std::move(value))
- {
- }
- template <class Tag,class T>
- inline
- error_info<Tag,T>::
- error_info( error_info && x ) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(value_type(std::move(x.value_)))):
- value_(std::move(x.value_))
- {
- }
-#endif
-
- template <class Tag,class T>
- inline
- error_info<Tag,T>::
- ~error_info() throw()
- {
- }
-
- template <class Tag,class T>
- inline
std::string
error_info<Tag,T>::
name_value_string() const
@@ -180,7 +142,11 @@ boost
refcount_ptr<error_info_container> p;
error_info_container_impl * c=new error_info_container_impl;
p.adopt(c);
- c->info_ = info_;
+ for( error_info_map::const_iterator i=info_.begin(),e=info_.end(); i!=e; ++i )
+ {
+ shared_ptr<error_info_base> cp(i->second->clone());
+ c->info_.insert(std::make_pair(i->first,cp));
+ }
return p;
}
};
diff --git a/boost/exception/info_tuple.hpp b/boost/exception/info_tuple.hpp
index 70154fd278..7c16d75151 100644
--- a/boost/exception/info_tuple.hpp
+++ b/boost/exception/info_tuple.hpp
@@ -5,6 +5,10 @@
#ifndef UUID_63EE924290FB11DC87BB856555D89593
#define UUID_63EE924290FB11DC87BB856555D89593
+
+#include <boost/exception/info.hpp>
+#include <boost/tuple/tuple.hpp>
+
#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
#pragma GCC system_header
#endif
@@ -12,9 +16,6 @@
#pragma warning(push,1)
#endif
-#include <boost/exception/info.hpp>
-#include <boost/tuple/tuple.hpp>
-
namespace
boost
{
diff --git a/boost/exception/to_string.hpp b/boost/exception/to_string.hpp
index 68541d2b8c..51425b10d1 100644
--- a/boost/exception/to_string.hpp
+++ b/boost/exception/to_string.hpp
@@ -5,6 +5,11 @@
#ifndef UUID_7E48761AD92811DC9011477D56D89593
#define UUID_7E48761AD92811DC9011477D56D89593
+
+#include <boost/utility/enable_if.hpp>
+#include <boost/exception/detail/is_output_streamable.hpp>
+#include <sstream>
+
#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
#pragma GCC system_header
#endif
@@ -12,10 +17,6 @@
#pragma warning(push,1)
#endif
-#include <boost/utility/enable_if.hpp>
-#include <boost/exception/detail/is_output_streamable.hpp>
-#include <sstream>
-
namespace
boost
{
diff --git a/boost/exception/to_string_stub.hpp b/boost/exception/to_string_stub.hpp
index b6ab31cf86..8ff5e47fd6 100644
--- a/boost/exception/to_string_stub.hpp
+++ b/boost/exception/to_string_stub.hpp
@@ -5,6 +5,11 @@
#ifndef UUID_E788439ED9F011DCB181F25B55D89593
#define UUID_E788439ED9F011DCB181F25B55D89593
+
+#include <boost/exception/to_string.hpp>
+#include <boost/exception/detail/object_hex_dump.hpp>
+#include <boost/assert.hpp>
+
#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
#pragma GCC system_header
#endif
@@ -12,10 +17,6 @@
#pragma warning(push,1)
#endif
-#include <boost/exception/to_string.hpp>
-#include <boost/exception/detail/object_hex_dump.hpp>
-#include <boost/assert.hpp>
-
namespace
boost
{
diff --git a/boost/fiber/algo/algorithm.hpp b/boost/fiber/algo/algorithm.hpp
index 9b846e774b..b22a5923d6 100644
--- a/boost/fiber/algo/algorithm.hpp
+++ b/boost/fiber/algo/algorithm.hpp
@@ -6,11 +6,13 @@
#ifndef BOOST_FIBERS_ALGO_ALGORITHM_H
#define BOOST_FIBERS_ALGO_ALGORITHM_H
-#include <cstddef>
+#include <atomic>
#include <chrono>
+#include <cstddef>
-#include <boost/config.hpp>
#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/intrusive_ptr.hpp>
#include <boost/fiber/properties.hpp>
#include <boost/fiber/detail/config.hpp>
@@ -26,7 +28,13 @@ class context;
namespace algo {
-struct BOOST_FIBERS_DECL algorithm {
+class BOOST_FIBERS_DECL algorithm {
+private:
+ std::atomic< std::size_t > use_count_{ 0 };
+
+public:
+ typedef intrusive_ptr< algorithm > ptr_t;
+
virtual ~algorithm() {}
virtual void awakened( context *) noexcept = 0;
@@ -38,6 +46,19 @@ struct BOOST_FIBERS_DECL algorithm {
virtual void suspend_until( std::chrono::steady_clock::time_point const&) noexcept = 0;
virtual void notify() noexcept = 0;
+
+ friend void intrusive_ptr_add_ref( algorithm * algo) noexcept {
+ BOOST_ASSERT( nullptr != algo);
+ algo->use_count_.fetch_add( 1, std::memory_order_relaxed);
+ }
+
+ friend void intrusive_ptr_release( algorithm * algo) noexcept {
+ BOOST_ASSERT( nullptr != algo);
+ if ( 1 == algo->use_count_.fetch_sub( 1, std::memory_order_release) ) {
+ std::atomic_thread_fence( std::memory_order_acquire);
+ delete algo;
+ }
+ }
};
class BOOST_FIBERS_DECL algorithm_with_properties_base : public algorithm {
@@ -60,7 +81,7 @@ struct algorithm_with_properties : public algorithm_with_properties_base {
// with: algorithm_with_properties<PROPS>::awakened(fb);
virtual void awakened( context * ctx) noexcept override final {
fiber_properties * props = super::get_properties( ctx);
- if ( nullptr == props) {
+ if ( BOOST_LIKELY( nullptr == props) ) {
// TODO: would be great if PROPS could be allocated on the new
// fiber's stack somehow
props = new_properties( ctx);
diff --git a/boost/fiber/algo/numa/work_stealing.hpp b/boost/fiber/algo/numa/work_stealing.hpp
new file mode 100644
index 0000000000..26032ab35e
--- /dev/null
+++ b/boost/fiber/algo/numa/work_stealing.hpp
@@ -0,0 +1,93 @@
+
+// Copyright Oliver Kowalke 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_FIBERS_ALGO_NUMA_WORK_STEALING_H
+#define BOOST_FIBERS_ALGO_NUMA_WORK_STEALING_H
+
+#include <condition_variable>
+#include <chrono>
+#include <cstddef>
+#include <cstdint>
+#include <mutex>
+#include <vector>
+
+#include <boost/config.hpp>
+#include <boost/intrusive_ptr.hpp>
+
+#include <boost/fiber/algo/algorithm.hpp>
+#include <boost/fiber/context.hpp>
+#include <boost/fiber/detail/config.hpp>
+#include <boost/fiber/detail/context_spinlock_queue.hpp>
+#include <boost/fiber/detail/context_spmc_queue.hpp>
+#include <boost/fiber/numa/pin_thread.hpp>
+#include <boost/fiber/numa/topology.hpp>
+#include <boost/fiber/scheduler.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace fibers {
+namespace algo {
+namespace numa {
+
+class work_stealing : public algorithm {
+private:
+ static std::vector< intrusive_ptr< work_stealing > > schedulers_;
+
+ std::uint32_t cpu_id_;
+ std::vector< std::uint32_t > local_cpus_;
+ std::vector< std::uint32_t > remote_cpus_;
+#ifdef BOOST_FIBERS_USE_SPMC_QUEUE
+ detail::context_spmc_queue rqueue_{};
+#else
+ detail::context_spinlock_queue rqueue_{};
+#endif
+ std::mutex mtx_{};
+ std::condition_variable cnd_{};
+ bool flag_{ false };
+ bool suspend_;
+
+ static void init_( std::vector< boost::fibers::numa::node > const&,
+ std::vector< intrusive_ptr< work_stealing > > &);
+
+public:
+ work_stealing( std::uint32_t, std::uint32_t,
+ std::vector< boost::fibers::numa::node > const&,
+ bool = false);
+
+ work_stealing( work_stealing const&) = delete;
+ work_stealing( work_stealing &&) = delete;
+
+ work_stealing & operator=( work_stealing const&) = delete;
+ work_stealing & operator=( work_stealing &&) = delete;
+
+ virtual void awakened( context *) noexcept;
+
+ virtual context * pick_next() noexcept;
+
+ virtual context * steal() noexcept {
+ return rqueue_.steal();
+ }
+
+ virtual bool has_ready_fibers() const noexcept {
+ return ! rqueue_.empty();
+ }
+
+ virtual void suspend_until( std::chrono::steady_clock::time_point const&) noexcept;
+
+ virtual void notify() noexcept;
+};
+
+}}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_FIBERS_ALGO_NUMA_WORK_STEALING_H
diff --git a/boost/fiber/algo/work_stealing.hpp b/boost/fiber/algo/work_stealing.hpp
index 66cadd12be..db4b5cf12d 100644
--- a/boost/fiber/algo/work_stealing.hpp
+++ b/boost/fiber/algo/work_stealing.hpp
@@ -8,19 +8,22 @@
#ifndef BOOST_FIBERS_ALGO_WORK_STEALING_H
#define BOOST_FIBERS_ALGO_WORK_STEALING_H
+#include <atomic>
#include <condition_variable>
#include <chrono>
#include <cstddef>
+#include <cstdint>
#include <mutex>
#include <vector>
#include <boost/config.hpp>
+#include <boost/intrusive_ptr.hpp>
#include <boost/fiber/algo/algorithm.hpp>
-#include <boost/fiber/detail/context_spinlock_queue.hpp>
-#include <boost/fiber/detail/context_spmc_queue.hpp>
#include <boost/fiber/context.hpp>
#include <boost/fiber/detail/config.hpp>
+#include <boost/fiber/detail/context_spinlock_queue.hpp>
+#include <boost/fiber/detail/context_spmc_queue.hpp>
#include <boost/fiber/scheduler.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
@@ -33,24 +36,25 @@ namespace algo {
class work_stealing : public algorithm {
private:
- static std::vector< work_stealing * > schedulers_;
+ static std::atomic< std::uint32_t > counter_;
+ static std::vector< intrusive_ptr< work_stealing > > schedulers_;
- std::size_t idx_;
- std::size_t max_idx_;
+ std::uint32_t id_;
+ std::uint32_t thread_count_;
#ifdef BOOST_FIBERS_USE_SPMC_QUEUE
- alignas(cache_alignment) detail::context_spmc_queue rqueue_{};
+ detail::context_spmc_queue rqueue_{};
#else
- alignas(cache_alignment) detail::context_spinlock_queue rqueue_{};
+ detail::context_spinlock_queue rqueue_{};
#endif
std::mutex mtx_{};
std::condition_variable cnd_{};
bool flag_{ false };
bool suspend_;
- static void init_( std::size_t max_idx);
+ static void init_( std::uint32_t, std::vector< intrusive_ptr< work_stealing > > &);
public:
- work_stealing( std::size_t max_idx, std::size_t idx, bool suspend = false);
+ work_stealing( std::uint32_t, bool = false);
work_stealing( work_stealing const&) = delete;
work_stealing( work_stealing &&) = delete;
@@ -58,21 +62,21 @@ public:
work_stealing & operator=( work_stealing const&) = delete;
work_stealing & operator=( work_stealing &&) = delete;
- void awakened( context * ctx) noexcept;
+ virtual void awakened( context *) noexcept;
- context * pick_next() noexcept;
+ virtual context * pick_next() noexcept;
- context * steal() noexcept {
+ virtual context * steal() noexcept {
return rqueue_.steal();
}
- bool has_ready_fibers() const noexcept {
+ virtual bool has_ready_fibers() const noexcept {
return ! rqueue_.empty();
}
- void suspend_until( std::chrono::steady_clock::time_point const& time_point) noexcept;
+ virtual void suspend_until( std::chrono::steady_clock::time_point const&) noexcept;
- void notify() noexcept;
+ virtual void notify() noexcept;
};
}}}
diff --git a/boost/fiber/all.hpp b/boost/fiber/all.hpp
index 460df5295b..17ceca45cc 100644
--- a/boost/fiber/all.hpp
+++ b/boost/fiber/all.hpp
@@ -11,6 +11,7 @@
#include <boost/fiber/algo/round_robin.hpp>
#include <boost/fiber/algo/shared_work.hpp>
#include <boost/fiber/algo/work_stealing.hpp>
+#include <boost/fiber/algo/numa/work_stealing.hpp>
#include <boost/fiber/barrier.hpp>
#include <boost/fiber/buffered_channel.hpp>
#include <boost/fiber/channel_op_status.hpp>
@@ -21,6 +22,8 @@
#include <boost/fiber/fixedsize_stack.hpp>
#include <boost/fiber/fss.hpp>
#include <boost/fiber/future.hpp>
+#include <boost/fiber/numa/pin_thread.hpp>
+#include <boost/fiber/numa/topology.hpp>
#include <boost/fiber/mutex.hpp>
#include <boost/fiber/operations.hpp>
#include <boost/fiber/policy.hpp>
diff --git a/boost/fiber/buffered_channel.hpp b/boost/fiber/buffered_channel.hpp
index 1c32e49bae..3cf22295dd 100644
--- a/boost/fiber/buffered_channel.hpp
+++ b/boost/fiber/buffered_channel.hpp
@@ -40,7 +40,7 @@ private:
typedef context::wait_queue_t wait_queue_type;
typedef T slot_type;
- alignas(cache_alignment) mutable detail::spinlock splk_{};
+ mutable detail::spinlock splk_{};
wait_queue_type waiting_producers_{};
wait_queue_type waiting_consumers_{};
slot_type * slots_;
@@ -64,7 +64,7 @@ private:
public:
explicit buffered_channel( std::size_t capacity) :
capacity_{ capacity } {
- if ( 2 > capacity_ || 0 != ( capacity_ & (capacity_ - 1) ) ) {
+ if ( BOOST_UNLIKELY( 2 > capacity_ || 0 != ( capacity_ & (capacity_ - 1) ) ) ) {
throw fiber_error{ std::make_error_code( std::errc::invalid_argument),
"boost fiber: buffer capacity is invalid" };
}
@@ -92,20 +92,52 @@ public:
while ( ! waiting_producers_.empty() ) {
context * producer_ctx = & waiting_producers_.front();
waiting_producers_.pop_front();
- active_ctx->schedule( producer_ctx);
+ std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+ if ( producer_ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+ // notify before timeout
+ intrusive_ptr_release( producer_ctx);
+ // notify context
+ active_ctx->schedule( producer_ctx);
+ } else if ( static_cast< std::intptr_t >( 0) == expected) {
+ // no timed-wait op.
+ // notify context
+ active_ctx->schedule( producer_ctx);
+ } else {
+ // timed-wait op.
+ // expected == -1: notify after timeout, same timed-wait op.
+ // expected == <any>: notify after timeout, another timed-wait op. was already started
+ intrusive_ptr_release( producer_ctx);
+ // re-schedule next
+ }
}
// notify all waiting consumers
while ( ! waiting_consumers_.empty() ) {
context * consumer_ctx = & waiting_consumers_.front();
waiting_consumers_.pop_front();
- active_ctx->schedule( consumer_ctx);
+ std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+ if ( consumer_ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+ // notify before timeout
+ intrusive_ptr_release( consumer_ctx);
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ } else if ( static_cast< std::intptr_t >( 0) == expected) {
+ // no timed-wait op.
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ } else {
+ // timed-wait op.
+ // expected == -1: notify after timeout, same timed-wait op.
+ // expected == <any>: notify after timeout, another timed-wait op. was already started
+ intrusive_ptr_release( consumer_ctx);
+ // re-schedule next
+ }
}
}
channel_op_status try_push( value_type const& value) {
context * active_ctx = context::active();
detail::spinlock_lock lk{ splk_ };
- if ( is_closed_() ) {
+ if ( BOOST_UNLIKELY( is_closed_() ) ) {
return channel_op_status::closed;
} else if ( is_full_() ) {
return channel_op_status::full;
@@ -113,11 +145,28 @@ public:
slots_[pidx_] = value;
pidx_ = (pidx_ + 1) % capacity_;
// notify one waiting consumer
- if ( ! waiting_consumers_.empty() ) {
+ while ( ! waiting_consumers_.empty() ) {
context * consumer_ctx = & waiting_consumers_.front();
waiting_consumers_.pop_front();
- lk.unlock();
- active_ctx->schedule( consumer_ctx);
+ std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+ if ( consumer_ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+ // notify before timeout
+ intrusive_ptr_release( consumer_ctx);
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ break;
+ } else if ( static_cast< std::intptr_t >( 0) == expected) {
+ // no timed-wait op.
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ break;
+ } else {
+ // timed-wait op.
+ // expected == -1: notify after timeout, same timed-wait op.
+ // expected == <any>: notify after timeout, another timed-wait op. was already started
+ intrusive_ptr_release( consumer_ctx);
+ // re-schedule next
+ }
}
return channel_op_status::success;
}
@@ -126,7 +175,7 @@ public:
channel_op_status try_push( value_type && value) {
context * active_ctx = context::active();
detail::spinlock_lock lk{ splk_ };
- if ( is_closed_() ) {
+ if ( BOOST_UNLIKELY( is_closed_() ) ) {
return channel_op_status::closed;
} else if ( is_full_() ) {
return channel_op_status::full;
@@ -134,11 +183,29 @@ public:
slots_[pidx_] = std::move( value);
pidx_ = (pidx_ + 1) % capacity_;
// notify one waiting consumer
- if ( ! waiting_consumers_.empty() ) {
+ while ( ! waiting_consumers_.empty() ) {
context * consumer_ctx = & waiting_consumers_.front();
waiting_consumers_.pop_front();
lk.unlock();
- active_ctx->schedule( consumer_ctx);
+ std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+ if ( consumer_ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+ // notify before timeout
+ intrusive_ptr_release( consumer_ctx);
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ break;
+ } else if ( static_cast< std::intptr_t >( 0) == expected) {
+ // no timed-wait op.
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ break;
+ } else {
+ // timed-wait op.
+ // expected == -1: notify after timeout, same timed-wait op.
+ // expected == <any>: notify after timeout, another timed-wait op. was already started
+ intrusive_ptr_release( consumer_ctx);
+ // re-schedule next
+ }
}
return channel_op_status::success;
}
@@ -148,21 +215,40 @@ public:
context * active_ctx = context::active();
for (;;) {
detail::spinlock_lock lk{ splk_ };
- if ( is_closed_() ) {
+ if ( BOOST_UNLIKELY( is_closed_() ) ) {
return channel_op_status::closed;
} else if ( is_full_() ) {
active_ctx->wait_link( waiting_producers_);
+ active_ctx->twstatus.store( static_cast< std::intptr_t >( 0), std::memory_order_release);
// suspend this producer
active_ctx->suspend( lk);
} else {
slots_[pidx_] = value;
pidx_ = (pidx_ + 1) % capacity_;
// notify one waiting consumer
- if ( ! waiting_consumers_.empty() ) {
+ while ( ! waiting_consumers_.empty() ) {
context * consumer_ctx = & waiting_consumers_.front();
waiting_consumers_.pop_front();
lk.unlock();
- active_ctx->schedule( consumer_ctx);
+ std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+ if ( consumer_ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+ // notify before timeout
+ intrusive_ptr_release( consumer_ctx);
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ break;
+ } else if ( static_cast< std::intptr_t >( 0) == expected) {
+ // no timed-wait op.
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ break;
+ } else {
+ // timed-wait op.
+ // expected == -1: notify after timeout, same timed-wait op.
+ // expected == <any>: notify after timeout, another timed-wait op. was already started
+ intrusive_ptr_release( consumer_ctx);
+ // re-schedule next
+ }
}
return channel_op_status::success;
}
@@ -173,21 +259,40 @@ public:
context * active_ctx = context::active();
for (;;) {
detail::spinlock_lock lk{ splk_ };
- if ( is_closed_() ) {
+ if ( BOOST_UNLIKELY( is_closed_() ) ) {
return channel_op_status::closed;
} else if ( is_full_() ) {
active_ctx->wait_link( waiting_producers_);
+ active_ctx->twstatus.store( static_cast< std::intptr_t >( 0), std::memory_order_release);
// suspend this producer
active_ctx->suspend( lk);
} else {
slots_[pidx_] = std::move( value);
pidx_ = (pidx_ + 1) % capacity_;
// notify one waiting consumer
- if ( ! waiting_consumers_.empty() ) {
+ while ( ! waiting_consumers_.empty() ) {
context * consumer_ctx = & waiting_consumers_.front();
waiting_consumers_.pop_front();
lk.unlock();
- active_ctx->schedule( consumer_ctx);
+ std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+ if ( consumer_ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+ // notify before timeout
+ intrusive_ptr_release( consumer_ctx);
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ break;
+ } else if ( static_cast< std::intptr_t >( 0) == expected) {
+ // no timed-wait op.
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ break;
+ } else {
+ // timed-wait op.
+ // expected == -1: notify after timeout, same timed-wait op.
+ // expected == <any>: notify after timeout, another timed-wait op. was already started
+ intrusive_ptr_release( consumer_ctx);
+ // re-schedule next
+ }
}
return channel_op_status::success;
}
@@ -215,10 +320,12 @@ public:
std::chrono::steady_clock::time_point timeout_time = detail::convert( timeout_time_);
for (;;) {
detail::spinlock_lock lk{ splk_ };
- if ( is_closed_() ) {
+ if ( BOOST_UNLIKELY( is_closed_() ) ) {
return channel_op_status::closed;
} else if ( is_full_() ) {
active_ctx->wait_link( waiting_producers_);
+ intrusive_ptr_add_ref( active_ctx);
+ active_ctx->twstatus.store( reinterpret_cast< std::intptr_t >( this), std::memory_order_release);
// suspend this producer
if ( ! active_ctx->wait_until( timeout_time, lk) ) {
// relock local lk
@@ -231,11 +338,29 @@ public:
slots_[pidx_] = value;
pidx_ = (pidx_ + 1) % capacity_;
// notify one waiting consumer
- if ( ! waiting_consumers_.empty() ) {
+ while ( ! waiting_consumers_.empty() ) {
context * consumer_ctx = & waiting_consumers_.front();
waiting_consumers_.pop_front();
lk.unlock();
- active_ctx->schedule( consumer_ctx);
+ std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+ if ( consumer_ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+ // notify before timeout
+ intrusive_ptr_release( consumer_ctx);
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ break;
+ } else if ( static_cast< std::intptr_t >( 0) == expected) {
+ // no timed-wait op.
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ break;
+ } else {
+ // timed-wait op.
+ // expected == -1: notify after timeout, same timed-wait op.
+ // expected == <any>: notify after timeout, another timed-wait op. was already started
+ intrusive_ptr_release( consumer_ctx);
+ // re-schedule next
+ }
}
return channel_op_status::success;
}
@@ -249,10 +374,12 @@ public:
std::chrono::steady_clock::time_point timeout_time = detail::convert( timeout_time_);
for (;;) {
detail::spinlock_lock lk{ splk_ };
- if ( is_closed_() ) {
+ if ( BOOST_UNLIKELY( is_closed_() ) ) {
return channel_op_status::closed;
} else if ( is_full_() ) {
active_ctx->wait_link( waiting_producers_);
+ intrusive_ptr_add_ref( active_ctx);
+ active_ctx->twstatus.store( reinterpret_cast< std::intptr_t >( this), std::memory_order_release);
// suspend this producer
if ( ! active_ctx->wait_until( timeout_time, lk) ) {
// relock local lk
@@ -265,11 +392,29 @@ public:
slots_[pidx_] = std::move( value);
pidx_ = (pidx_ + 1) % capacity_;
// notify one waiting consumer
- if ( ! waiting_consumers_.empty() ) {
+ while ( ! waiting_consumers_.empty() ) {
context * consumer_ctx = & waiting_consumers_.front();
waiting_consumers_.pop_front();
lk.unlock();
- active_ctx->schedule( consumer_ctx);
+ std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+ if ( consumer_ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+ // notify before timeout
+ intrusive_ptr_release( consumer_ctx);
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ break;
+ } else if ( static_cast< std::intptr_t >( 0) == expected) {
+ // no timed-wait op.
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ break;
+ } else {
+ // timed-wait op.
+ // expected == -1: notify after timeout, same timed-wait op.
+ // expected == <any>: notify after timeout, another timed-wait op. was already started
+ intrusive_ptr_release( consumer_ctx);
+ // re-schedule next
+ }
}
return channel_op_status::success;
}
@@ -287,11 +432,29 @@ public:
value = std::move( slots_[cidx_]);
cidx_ = (cidx_ + 1) % capacity_;
// notify one waiting producer
- if ( ! waiting_producers_.empty() ) {
+ while ( ! waiting_producers_.empty() ) {
context * producer_ctx = & waiting_producers_.front();
waiting_producers_.pop_front();
lk.unlock();
- active_ctx->schedule( producer_ctx);
+ std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+ if ( producer_ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+ // notify before timeout
+ intrusive_ptr_release( producer_ctx);
+ // notify context
+ active_ctx->schedule( producer_ctx);
+ break;
+ } else if ( static_cast< std::intptr_t >( 0) == expected) {
+ // no timed-wait op.
+ // notify context
+ active_ctx->schedule( producer_ctx);
+ break;
+ } else {
+ // timed-wait op.
+ // expected == -1: notify after timeout, same timed-wait op.
+ // expected == <any>: notify after timeout, another timed-wait op. was already started
+ intrusive_ptr_release( producer_ctx);
+ // re-schedule next
+ }
}
return channel_op_status::success;
}
@@ -302,10 +465,11 @@ public:
for (;;) {
detail::spinlock_lock lk{ splk_ };
if ( is_empty_() ) {
- if ( is_closed_() ) {
+ if ( BOOST_UNLIKELY( is_closed_() ) ) {
return channel_op_status::closed;
} else {
active_ctx->wait_link( waiting_consumers_);
+ active_ctx->twstatus.store( static_cast< std::intptr_t >( 0), std::memory_order_release);
// suspend this consumer
active_ctx->suspend( lk);
}
@@ -313,11 +477,29 @@ public:
value = std::move( slots_[cidx_]);
cidx_ = (cidx_ + 1) % capacity_;
// notify one waiting producer
- if ( ! waiting_producers_.empty() ) {
+ while ( ! waiting_producers_.empty() ) {
context * producer_ctx = & waiting_producers_.front();
waiting_producers_.pop_front();
lk.unlock();
- active_ctx->schedule( producer_ctx);
+ std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+ if ( producer_ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+ // notify before timeout
+ intrusive_ptr_release( producer_ctx);
+ // notify context
+ active_ctx->schedule( producer_ctx);
+ break;
+ } else if ( static_cast< std::intptr_t >( 0) == expected) {
+ // no timed-wait op.
+ // notify context
+ active_ctx->schedule( producer_ctx);
+ break;
+ } else {
+ // timed-wait op.
+ // expected == -1: notify after timeout, same timed-wait op.
+ // expected == <any>: notify after timeout, another timed-wait op. was already started
+ intrusive_ptr_release( producer_ctx);
+ // re-schedule next
+ }
}
return channel_op_status::success;
}
@@ -329,12 +511,13 @@ public:
for (;;) {
detail::spinlock_lock lk{ splk_ };
if ( is_empty_() ) {
- if ( is_closed_() ) {
+ if ( BOOST_UNLIKELY( is_closed_() ) ) {
throw fiber_error{
std::make_error_code( std::errc::operation_not_permitted),
"boost fiber: channel is closed" };
} else {
active_ctx->wait_link( waiting_consumers_);
+ active_ctx->twstatus.store( static_cast< std::intptr_t >( 0), std::memory_order_release);
// suspend this consumer
active_ctx->suspend( lk);
}
@@ -342,11 +525,29 @@ public:
value_type value = std::move( slots_[cidx_]);
cidx_ = (cidx_ + 1) % capacity_;
// notify one waiting producer
- if ( ! waiting_producers_.empty() ) {
+ while ( ! waiting_producers_.empty() ) {
context * producer_ctx = & waiting_producers_.front();
waiting_producers_.pop_front();
lk.unlock();
- active_ctx->schedule( producer_ctx);
+ std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+ if ( producer_ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+ // notify before timeout
+ intrusive_ptr_release( producer_ctx);
+ // notify context
+ active_ctx->schedule( producer_ctx);
+ break;
+ } else if ( static_cast< std::intptr_t >( 0) == expected) {
+ // no timed-wait op.
+ // notify context
+ active_ctx->schedule( producer_ctx);
+ break;
+ } else {
+ // timed-wait op.
+ // expected == -1: notify after timeout, same timed-wait op.
+ // expected == <any>: notify after timeout, another timed-wait op. was already started
+ intrusive_ptr_release( producer_ctx);
+ // re-schedule next
+ }
}
return std::move( value);
}
@@ -368,10 +569,12 @@ public:
for (;;) {
detail::spinlock_lock lk{ splk_ };
if ( is_empty_() ) {
- if ( is_closed_() ) {
+ if ( BOOST_UNLIKELY( is_closed_() ) ) {
return channel_op_status::closed;
} else {
active_ctx->wait_link( waiting_consumers_);
+ intrusive_ptr_add_ref( active_ctx);
+ active_ctx->twstatus.store( reinterpret_cast< std::intptr_t >( this), std::memory_order_release);
// suspend this consumer
if ( ! active_ctx->wait_until( timeout_time, lk) ) {
// relock local lk
@@ -385,11 +588,29 @@ public:
value = std::move( slots_[cidx_]);
cidx_ = (cidx_ + 1) % capacity_;
// notify one waiting producer
- if ( ! waiting_producers_.empty() ) {
+ while ( ! waiting_producers_.empty() ) {
context * producer_ctx = & waiting_producers_.front();
waiting_producers_.pop_front();
lk.unlock();
- active_ctx->schedule( producer_ctx);
+ std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+ if ( producer_ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+ // notify before timeout
+ intrusive_ptr_release( producer_ctx);
+ // notify context
+ active_ctx->schedule( producer_ctx);
+ break;
+ } else if ( static_cast< std::intptr_t >( 0) == expected) {
+ // no timed-wait op.
+ // notify context
+ active_ctx->schedule( producer_ctx);
+ break;
+ } else {
+ // timed-wait op.
+ // expected == -1: notify after timeout, same timed-wait op.
+ // expected == <any>: notify after timeout, another timed-wait op. was already started
+ intrusive_ptr_release( producer_ctx);
+ // re-schedule next
+ }
}
return channel_op_status::success;
}
@@ -428,8 +649,9 @@ public:
}
iterator & operator=( iterator const& other) noexcept {
- if ( this == & other) return * this;
- chan_ = other.chan_;
+ if ( BOOST_LIKELY( this != & other) ) {
+ chan_ = other.chan_;
+ }
return * this;
}
diff --git a/boost/fiber/condition_variable.hpp b/boost/fiber/condition_variable.hpp
index cd0e7cb022..2cd3ecc719 100644
--- a/boost/fiber/condition_variable.hpp
+++ b/boost/fiber/condition_variable.hpp
@@ -70,6 +70,7 @@ public:
detail::spinlock_lock lk{ wait_queue_splk_ };
BOOST_ASSERT( ! active_ctx->wait_is_linked() );
active_ctx->wait_link( wait_queue_);
+ active_ctx->twstatus.store( static_cast< std::intptr_t >( 0), std::memory_order_release);
// unlock external lt
lt.unlock();
// suspend this fiber
@@ -101,6 +102,8 @@ public:
detail::spinlock_lock lk{ wait_queue_splk_ };
BOOST_ASSERT( ! active_ctx->wait_is_linked() );
active_ctx->wait_link( wait_queue_);
+ intrusive_ptr_add_ref( active_ctx);
+ active_ctx->twstatus.store( reinterpret_cast< std::intptr_t >( this), std::memory_order_release);
// unlock external lt
lt.unlock();
// suspend this fiber
diff --git a/boost/fiber/context.hpp b/boost/fiber/context.hpp
index 773528e3a1..e2d1aeff5f 100644
--- a/boost/fiber/context.hpp
+++ b/boost/fiber/context.hpp
@@ -7,11 +7,12 @@
#ifndef BOOST_FIBERS_CONTEXT_H
#define BOOST_FIBERS_CONTEXT_H
-#include <iostream>
#include <atomic>
#include <chrono>
+#include <cstdint>
#include <exception>
#include <functional>
+#include <iostream>
#include <map>
#include <memory>
#include <tuple>
@@ -22,11 +23,7 @@
#if defined(BOOST_NO_CXX17_STD_APPLY)
#include <boost/context/detail/apply.hpp>
#endif
-#if (BOOST_EXECUTION_CONTEXT==1)
-# include <boost/context/execution_context.hpp>
-#else
-# include <boost/context/continuation.hpp>
-#endif
+#include <boost/context/continuation.hpp>
#include <boost/context/stack_context.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/parent_from_member.hpp>
@@ -39,7 +36,6 @@
#include <boost/fiber/detail/decay_copy.hpp>
#include <boost/fiber/detail/fss.hpp>
#include <boost/fiber/detail/spinlock.hpp>
-#include <boost/fiber/detail/wrap.hpp>
#include <boost/fiber/exceptions.hpp>
#include <boost/fiber/fixedsize_stack.hpp>
#include <boost/fiber/policy.hpp>
@@ -66,10 +62,10 @@ class scheduler;
namespace detail {
struct wait_tag;
-typedef intrusive::slist_member_hook<
+typedef intrusive::list_member_hook<
intrusive::tag< wait_tag >,
intrusive::link_mode<
- intrusive::safe_link
+ intrusive::auto_unlink
>
> wait_hook;
// declaration of the functor that converts between
@@ -132,25 +128,18 @@ typedef intrusive::slist_member_hook<
}
-struct main_context_t {};
-const main_context_t main_context{};
-
-struct dispatcher_context_t {};
-const dispatcher_context_t dispatcher_context{};
-
-struct worker_context_t {};
-const worker_context_t worker_context{};
-
class BOOST_FIBERS_DECL context {
public:
- typedef intrusive::slist<
+ typedef intrusive::list<
context,
intrusive::function_hook< detail::wait_functor >,
- intrusive::linear< true >,
- intrusive::cache_last< true >
+ intrusive::constant_time_size< false >
> wait_queue_t;
private:
+ friend class dispatcher_context;
+ friend class main_context;
+ template< typename Fn, typename ... Arg > friend class worker_context;
friend class scheduler;
struct fss_data {
@@ -175,88 +164,39 @@ private:
typedef std::map< uintptr_t, fss_data > fss_data_t;
#if ! defined(BOOST_FIBERS_NO_ATOMICS)
- alignas(cache_alignment) std::atomic< std::size_t > use_count_{ 0 };
+ std::atomic< std::size_t > use_count_;
#else
- alignas(cache_alignment) std::size_t use_count_{ 0 };
+ std::size_t use_count_;
#endif
#if ! defined(BOOST_FIBERS_NO_ATOMICS)
- alignas(cache_alignment) detail::remote_ready_hook remote_ready_hook_{};
- std::atomic< context * > remote_nxt_{ nullptr };
+ detail::remote_ready_hook remote_ready_hook_{};
#endif
- alignas(cache_alignment) detail::spinlock splk_{};
+ detail::spinlock splk_{};
bool terminated_{ false };
wait_queue_t wait_queue_{};
public:
detail::wait_hook wait_hook_{};
+#if ! defined(BOOST_FIBERS_NO_ATOMICS)
+ std::atomic< std::intptr_t > twstatus{ 0 };
+#endif
private:
- alignas(cache_alignment) scheduler * scheduler_{ nullptr };
+ scheduler * scheduler_{ nullptr };
fss_data_t fss_data_{};
detail::sleep_hook sleep_hook_{};
detail::ready_hook ready_hook_{};
detail::terminated_hook terminated_hook_{};
detail::worker_hook worker_hook_{};
-#if (BOOST_EXECUTION_CONTEXT==1)
- boost::context::execution_context ctx_;
-#else
- boost::context::continuation c_;
-#endif
fiber_properties * properties_{ nullptr };
std::chrono::steady_clock::time_point tp_{ (std::chrono::steady_clock::time_point::max)() };
+ boost::context::continuation c_{};
type type_;
launch policy_;
- void resume_( detail::data_t &) noexcept;
- void schedule_( context *) noexcept;
-
-#if (BOOST_EXECUTION_CONTEXT==1)
- template< typename Fn, typename Tpl >
- void run_( Fn && fn_, Tpl && tpl_, detail::data_t * dp) noexcept {
- {
- // fn and tpl must be destroyed before calling terminate()
- typename std::decay< Fn >::type fn = std::forward< Fn >( fn_);
- typename std::decay< Tpl >::type tpl = std::forward< Tpl >( tpl_);
- if ( nullptr != dp->lk) {
- dp->lk->unlock();
- } else if ( nullptr != dp->ctx) {
- active()->schedule_( dp->ctx);
- }
-#if defined(BOOST_NO_CXX17_STD_APPLY)
- boost::context::detail::apply( std::move( fn), std::move( tpl) );
-#else
- std::apply( std::move( fn), std::move( tpl) );
-#endif
- }
- // terminate context
- terminate();
- BOOST_ASSERT_MSG( false, "fiber already terminated");
- }
-#else
- template< typename Fn, typename Tpl >
- boost::context::continuation
- run_( boost::context::continuation && c, Fn && fn_, Tpl && tpl_) noexcept {
- {
- // fn and tpl must be destroyed before calling terminate()
- typename std::decay< Fn >::type fn = std::forward< Fn >( fn_);
- typename std::decay< Tpl >::type tpl = std::forward< Tpl >( tpl_);
- c = c.resume();
- detail::data_t * dp = c.get_data< detail::data_t * >();
- // update contiunation of calling fiber
- dp->from->c_ = std::move( c);
- if ( nullptr != dp->lk) {
- dp->lk->unlock();
- } else if ( nullptr != dp->ctx) {
- active()->schedule_( dp->ctx);
- }
-#if defined(BOOST_NO_CXX17_STD_APPLY)
- boost::context::detail::apply( std::move( fn), std::move( tpl) );
-#else
- std::apply( std::move( fn), std::move( tpl) );
-#endif
- }
- // terminate context
- return terminate();
+ context( std::size_t initial_count, type t, launch policy) noexcept :
+ use_count_{ initial_count },
+ type_{ t },
+ policy_{ policy } {
}
-#endif
public:
class id {
@@ -317,73 +257,6 @@ public:
static void reset_active() noexcept;
- // main fiber context
- explicit context( main_context_t) noexcept;
-
- // dispatcher fiber context
- context( dispatcher_context_t, boost::context::preallocated const&,
- default_stack const&, scheduler *);
-
- // worker fiber context
- template< typename StackAlloc,
- typename Fn,
- typename Tpl
- >
- context( worker_context_t,
- launch policy,
- boost::context::preallocated palloc, StackAlloc salloc,
- Fn && fn, Tpl && tpl) :
- use_count_{ 1 }, // fiber instance or scheduler owner
-#if (BOOST_EXECUTION_CONTEXT==1)
-# if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
- ctx_{ std::allocator_arg, palloc, salloc,
- detail::wrap(
- [this]( typename std::decay< Fn >::type & fn, typename std::decay< Tpl >::type & tpl,
- boost::context::execution_context & ctx, void * vp) mutable noexcept {
- run_( std::move( fn), std::move( tpl), static_cast< detail::data_t * >( vp) );
- },
- std::forward< Fn >( fn),
- std::forward< Tpl >( tpl),
- boost::context::execution_context::current() )
- },
- type_{ type::worker_context },
- policy_{ policy }
-# else
- ctx_{ std::allocator_arg, palloc, salloc,
- [this,fn=detail::decay_copy( std::forward< Fn >( fn) ),tpl=std::forward< Tpl >( tpl),
- ctx=boost::context::execution_context::current()] (void * vp) mutable noexcept {
- run_( std::move( fn), std::move( tpl), static_cast< detail::data_t * >( vp) );
- }},
- type_{ type::worker_context },
- policy_{ policy }
-# endif
- {}
-#else
- c_{},
- type_{ type::worker_context },
- policy_{ policy }
- {
-# if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
- c_ = boost::context::callcc(
- std::allocator_arg, palloc, salloc,
- detail::wrap(
- [this]( typename std::decay< Fn >::type & fn, typename std::decay< Tpl >::type & tpl,
- boost::context::continuation && c) mutable noexcept {
- return run_( std::forward< boost::context::continuation >( c), std::move( fn), std::move( tpl) );
- },
- std::forward< Fn >( fn),
- std::forward< Tpl >( tpl) ) );
-# else
- c_ = boost::context::callcc(
- std::allocator_arg, palloc, salloc,
- [this,fn=detail::decay_copy( std::forward< Fn >( fn) ),tpl=std::forward< Tpl >( tpl)]
- (boost::context::continuation && c) mutable noexcept {
- return run_( std::forward< boost::context::continuation >( c), std::move( fn), std::move( tpl) );
- });
-# endif
- }
-#endif
-
context( context const&) = delete;
context & operator=( context const&) = delete;
@@ -412,12 +285,9 @@ public:
void suspend() noexcept;
void suspend( detail::spinlock_lock &) noexcept;
-#if (BOOST_EXECUTION_CONTEXT==1)
- void terminate() noexcept;
-#else
boost::context::continuation suspend_with_cc() noexcept;
boost::context::continuation terminate() noexcept;
-#endif
+
void join();
void yield() noexcept;
@@ -510,6 +380,8 @@ public:
void sleep_unlink() noexcept;
+ void wait_unlink() noexcept;
+
void detach() noexcept;
void attach( context *) noexcept;
@@ -523,18 +395,11 @@ public:
BOOST_ASSERT( nullptr != ctx);
if ( 1 == ctx->use_count_.fetch_sub( 1, std::memory_order_release) ) {
std::atomic_thread_fence( std::memory_order_acquire);
-#if (BOOST_EXECUTION_CONTEXT==1)
- boost::context::execution_context ec = ctx->ctx_;
- // destruct context
- // deallocates stack (execution_context is ref counted)
- ctx->~context();
-#else
boost::context::continuation c = std::move( ctx->c_);
// destruct context
ctx->~context();
// deallocated stack
- c.resume( nullptr);
-#endif
+ c.resume();
}
}
};
@@ -544,36 +409,66 @@ bool operator<( context const& l, context const& r) noexcept {
return l.get_id() < r.get_id();
}
-template< typename StackAlloc, typename Fn, typename ... Args >
+template< typename Fn, typename ... Arg >
+class worker_context final : public context {
+private:
+ typename std::decay< Fn >::type fn_;
+ std::tuple< Arg ... > arg_;
+
+ boost::context::continuation
+ run_( boost::context::continuation && c) {
+ {
+ // fn and tpl must be destroyed before calling terminate()
+ auto fn = std::move( fn_);
+ auto arg = std::move( arg_);
+ c.resume();
+#if defined(BOOST_NO_CXX17_STD_APPLY)
+ boost::context::detail::apply( std::move( fn_), std::move( arg_) );
+#else
+ std::apply( std::move( fn_), std::move( arg_) );
+#endif
+ }
+ // terminate context
+ return terminate();
+ }
+
+public:
+ template< typename StackAlloc >
+ worker_context( launch policy,
+ boost::context::preallocated const& palloc, StackAlloc const& salloc,
+ Fn && fn, Arg ... arg) :
+ context{ 1, type::worker_context, policy },
+ fn_( std::forward< Fn >( fn) ),
+ arg_( std::forward< Arg >( arg) ... ) {
+ c_ = boost::context::callcc(
+ std::allocator_arg, palloc, salloc,
+ std::bind( & worker_context::run_, this, std::placeholders::_1) );
+ }
+};
+
+
+template< typename StackAlloc, typename Fn, typename ... Arg >
static intrusive_ptr< context > make_worker_context( launch policy,
StackAlloc salloc,
- Fn && fn, Args && ... args) {
- boost::context::stack_context sctx = salloc.allocate();
-#if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
+ Fn && fn, Arg ... arg) {
+ typedef worker_context< Fn, Arg ... > context_t;
+
+ auto sctx = salloc.allocate();
// reserve space for control structure
- const std::size_t size = sctx.size - sizeof( context);
- void * sp = static_cast< char * >( sctx.sp) - sizeof( context);
-#else
- constexpr std::size_t func_alignment = 64; // alignof( context);
- constexpr std::size_t func_size = sizeof( context);
- // reserve space on stack
- void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
- // align sp pointer
- std::size_t space = func_size + func_alignment;
- sp = std::align( func_alignment, func_size, sp, space);
- BOOST_ASSERT( nullptr != sp);
- // calculate remaining size
- const std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
-#endif
+ void * storage = reinterpret_cast< void * >(
+ ( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sizeof( context_t) ) )
+ & ~ static_cast< uintptr_t >( 0xff) );
+ void * stack_bottom = reinterpret_cast< void * >(
+ reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sctx.size) );
+ const std::size_t size = reinterpret_cast< uintptr_t >( storage) - reinterpret_cast< uintptr_t >( stack_bottom);
// placement new of context on top of fiber's stack
return intrusive_ptr< context >{
- ::new ( sp) context{
- worker_context,
+ new ( storage) context_t{
policy,
- boost::context::preallocated{ sp, size, sctx },
+ boost::context::preallocated{ storage, size, sctx },
salloc,
std::forward< Fn >( fn),
- std::make_tuple( std::forward< Args >( args) ... ) } };
+ std::forward< Arg >( arg) ... } };
}
namespace detail {
diff --git a/boost/fiber/detail/config.hpp b/boost/fiber/detail/config.hpp
index 7c7119e1fb..21dea693ac 100644
--- a/boost/fiber/detail/config.hpp
+++ b/boost/fiber/detail/config.hpp
@@ -47,19 +47,20 @@
# error "futex not supported on this platform"
#endif
-#if !defined(BOOST_FIBERS_SPIN_MAX_COLLISIONS)
-# define BOOST_FIBERS_SPIN_MAX_COLLISIONS 16
+#if !defined(BOOST_FIBERS_CONTENTION_WINDOW_THRESHOLD)
+# define BOOST_FIBERS_CONTENTION_WINDOW_THRESHOLD 16
#endif
-#if !defined(BOOST_FIBERS_SPIN_MAX_TESTS)
-# define BOOST_FIBERS_SPIN_MAX_TESTS 500
+#if !defined(BOOST_FIBERS_RETRY_THRESHOLD)
+# define BOOST_FIBERS_RETRY_THRESHOLD 64
#endif
-// modern architectures have cachelines with 64byte length
-// ARM Cortex-A15 32/64byte, Cortex-A9 16/32/64bytes
-// MIPS 74K: 32byte, 4KEc: 16byte
-// ist shoudl be safe to use 64byte for all
-static constexpr std::size_t cache_alignment{ 64 };
-static constexpr std::size_t cacheline_length{ 64 };
+#if !defined(BOOST_FIBERS_SPIN_BEFORE_SLEEP0)
+# define BOOST_FIBERS_SPIN_BEFORE_SLEEP0 32
+#endif
+
+#if !defined(BOOST_FIBERS_SPIN_BEFORE_YIELD)
+# define BOOST_FIBERS_SPIN_BEFORE_YIELD 64
+#endif
#endif // BOOST_FIBERS_DETAIL_CONFIG_H
diff --git a/boost/fiber/detail/context_spinlock_queue.hpp b/boost/fiber/detail/context_spinlock_queue.hpp
index e0ebdabda6..f58fbd2296 100644
--- a/boost/fiber/detail/context_spinlock_queue.hpp
+++ b/boost/fiber/detail/context_spinlock_queue.hpp
@@ -30,7 +30,7 @@ class context_spinlock_queue {
private:
typedef context * slot_type;
- alignas(cache_alignment) mutable spinlock splk_{};
+ mutable spinlock splk_{};
std::size_t pidx_{ 0 };
std::size_t cidx_{ 0 };
std::size_t capacity_;
diff --git a/boost/fiber/detail/context_spmc_queue.hpp b/boost/fiber/detail/context_spmc_queue.hpp
index 27256233cf..89f93044f9 100644
--- a/boost/fiber/detail/context_spmc_queue.hpp
+++ b/boost/fiber/detail/context_spmc_queue.hpp
@@ -44,9 +44,7 @@ private:
class array {
private:
typedef std::atomic< context * > atomic_type;
- typedef std::aligned_storage<
- sizeof( atomic_type), cache_alignment
- >::type storage_type;
+ typedef atomic_type storage_type;
std::size_t capacity_;
storage_type * storage_;
@@ -92,9 +90,9 @@ private:
}
};
- alignas(cache_alignment) std::atomic< std::size_t > top_{ 0 };
- alignas(cache_alignment) std::atomic< std::size_t > bottom_{ 0 };
- alignas(cache_alignment) std::atomic< array * > array_;
+ std::atomic< std::size_t > top_{ 0 };
+ std::atomic< std::size_t > bottom_{ 0 };
+ std::atomic< array * > array_;
std::vector< array * > old_arrays_{};
char padding_[cacheline_length];
diff --git a/boost/fiber/detail/convert.hpp b/boost/fiber/detail/convert.hpp
index ac190d8528..ba3bbbd0aa 100644
--- a/boost/fiber/detail/convert.hpp
+++ b/boost/fiber/detail/convert.hpp
@@ -34,22 +34,6 @@ std::chrono::steady_clock::time_point convert(
return std::chrono::steady_clock::now() + ( timeout_time - Clock::now() );
}
-// suggested by Howard Hinnant
-template< typename T >
-inline
-T * convert( T * p) noexcept {
- return p;
-}
-
-template< typename Pointer >
-inline
-typename std::pointer_traits< Pointer >::element_type *
-convert( Pointer p) noexcept {
- return nullptr != p
- ? to_raw_pointer( p.operator->() )
- : nullptr;
-}
-
}}}
#ifdef BOOST_HAS_ABI_HEADERS
diff --git a/boost/fiber/detail/cpu_relax.hpp b/boost/fiber/detail/cpu_relax.hpp
index 541b46dfd0..8a20aae059 100644
--- a/boost/fiber/detail/cpu_relax.hpp
+++ b/boost/fiber/detail/cpu_relax.hpp
@@ -16,7 +16,7 @@
#include <boost/fiber/detail/config.hpp>
#if BOOST_COMP_MSVC || BOOST_COMP_MSVC_EMULATED
-# include <Windows.h>
+# include <windows.h>
#endif
#ifdef BOOST_HAS_ABI_HEADERS
diff --git a/boost/fiber/detail/data.hpp b/boost/fiber/detail/data.hpp
index e2b119ec3e..c363817a09 100644
--- a/boost/fiber/detail/data.hpp
+++ b/boost/fiber/detail/data.hpp
@@ -23,22 +23,6 @@ class context;
namespace detail {
-#if (BOOST_EXECUTION_CONTEXT==1)
-struct data_t {
- spinlock_lock * lk{ nullptr };
- context * ctx{ nullptr };
-
- data_t() = default;
-
- explicit data_t( spinlock_lock * lk_) noexcept :
- lk{ lk_ } {
- }
-
- explicit data_t( context * ctx_) noexcept :
- ctx{ ctx_ } {
- }
-};
-#else
struct data_t {
spinlock_lock * lk{ nullptr };
context * ctx{ nullptr };
@@ -60,7 +44,6 @@ struct data_t {
from{ from_ } {
}
};
-#endif
}}}
diff --git a/boost/fiber/detail/futex.hpp b/boost/fiber/detail/futex.hpp
index d383dc4077..e64bd5990d 100644
--- a/boost/fiber/detail/futex.hpp
+++ b/boost/fiber/detail/futex.hpp
@@ -18,7 +18,7 @@ extern "C" {
#include <sys/syscall.h>
}
#elif BOOST_OS_WINDOWS
-#include <Windows.h>
+#include <windows.h>
#endif
namespace boost {
@@ -26,28 +26,28 @@ namespace fibers {
namespace detail {
#if BOOST_OS_LINUX
-inline
+BOOST_FORCEINLINE
int sys_futex( void * addr, std::int32_t op, std::int32_t x) {
return ::syscall( SYS_futex, addr, op, x, nullptr, nullptr, 0);
}
-inline
+BOOST_FORCEINLINE
int futex_wake( std::atomic< std::int32_t > * addr) {
return 0 <= sys_futex( static_cast< void * >( addr), FUTEX_WAKE_PRIVATE, 1) ? 0 : -1;
}
-inline
+BOOST_FORCEINLINE
int futex_wait( std::atomic< std::int32_t > * addr, std::int32_t x) {
return 0 <= sys_futex( static_cast< void * >( addr), FUTEX_WAIT_PRIVATE, x) ? 0 : -1;
}
#elif BOOST_OS_WINDOWS
-inline
+BOOST_FORCEINLINE
int futex_wake( std::atomic< std::int32_t > * addr) {
::WakeByAddressSingle( static_cast< void * >( addr) );
return 0;
}
-inline
+BOOST_FORCEINLINE
int futex_wait( std::atomic< std::int32_t > * addr, std::int32_t x) {
::WaitOnAddress( static_cast< volatile void * >( addr), & x, sizeof( x), INFINITE);
return 0;
diff --git a/boost/fiber/detail/rtm.hpp b/boost/fiber/detail/rtm.hpp
new file mode 100644
index 0000000000..5188b0d216
--- /dev/null
+++ b/boost/fiber/detail/rtm.hpp
@@ -0,0 +1,94 @@
+
+// Copyright Oliver Kowalke 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_FIBER_DETAIL_RTM_H
+#define BOOST_FIBER_DETAIL_RTM_H
+
+#include <cstdint>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+#include <boost/fiber/detail/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace fibers {
+namespace detail {
+
+struct rtm_status {
+ enum {
+ none = 0,
+ explicit_abort = 1 << 0,
+ may_retry = 1 << 1,
+ memory_conflict = 1 << 2,
+ buffer_overflow = 1 << 3,
+ debug_hit = 1 << 4,
+ nested_abort = 1 << 5
+ };
+
+ static constexpr std::uint32_t success = ~std::uint32_t{ 0 };
+};
+
+static BOOST_FORCEINLINE
+std::uint32_t rtm_begin() noexcept {
+ std::uint32_t result = rtm_status::success;
+ __asm__ __volatile__
+ (
+ ".byte 0xc7,0xf8 ; .long 0"
+ : "+a" (result)
+ :
+ : "memory"
+ );
+ return result;
+}
+
+static BOOST_FORCEINLINE
+void rtm_end() noexcept {
+ __asm__ __volatile__
+ (
+ ".byte 0x0f,0x01,0xd5"
+ :
+ :
+ : "memory"
+ );
+}
+
+static BOOST_FORCEINLINE
+void rtm_abort_lock_not_free() noexcept {
+ __asm__ __volatile__
+ (
+ ".byte 0xc6,0xf8,0xff"
+ :
+ :
+ : "memory"
+ );
+}
+
+static BOOST_FORCEINLINE
+bool rtm_test() noexcept {
+ bool result;
+ __asm__ __volatile__
+ (
+ ".byte 0x0f,0x01,0xd6; setz %0"
+ : "=q" (result)
+ :
+ : "memory"
+ );
+ return result;
+}
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_FIBER_DETAIL_RTM_H
diff --git a/boost/fiber/detail/spinlock.hpp b/boost/fiber/detail/spinlock.hpp
index 89a6d51a6f..59d2a5cd2b 100644
--- a/boost/fiber/detail/spinlock.hpp
+++ b/boost/fiber/detail/spinlock.hpp
@@ -13,11 +13,14 @@
#if !defined(BOOST_FIBERS_NO_ATOMICS)
# include <mutex>
-# include <boost/fiber/detail/spinlock_ttas.hpp>
# include <boost/fiber/detail/spinlock_ttas_adaptive.hpp>
+# include <boost/fiber/detail/spinlock_ttas.hpp>
# if defined(BOOST_FIBERS_HAS_FUTEX)
-# include <boost/fiber/detail/spinlock_ttas_futex.hpp>
# include <boost/fiber/detail/spinlock_ttas_adaptive_futex.hpp>
+# include <boost/fiber/detail/spinlock_ttas_futex.hpp>
+# endif
+# if defined(BOOST_USE_TSX)
+# include <boost/fiber/detail/spinlock_rtm.hpp>
# endif
#endif
@@ -29,7 +32,7 @@ namespace boost {
namespace fibers {
namespace detail {
-#if defined(BOOST_FIBERS_NO_ATOMICS)
+#if defined(BOOST_FIBERS_NO_ATOMICS)
struct spinlock {
constexpr spinlock() noexcept {}
void lock() noexcept {}
@@ -42,16 +45,32 @@ struct spinlock_lock {
void unlock() noexcept {}
};
#else
-# if defined(BOOST_FIBERS_SPINLOCK_STD_MUTEX)
+# if defined(BOOST_FIBERS_SPINLOCK_STD_MUTEX)
using spinlock = std::mutex;
# elif defined(BOOST_FIBERS_SPINLOCK_TTAS_FUTEX)
+# if defined(BOOST_USE_TSX)
+using spinlock = spinlock_rtm< spinlock_ttas_futex >;
+# else
using spinlock = spinlock_ttas_futex;
+# endif
# elif defined(BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE_FUTEX)
+# if defined(BOOST_USE_TSX)
+using spinlock = spinlock_rtm< spinlock_ttas_adaptive_futex >;
+# else
using spinlock = spinlock_ttas_adaptive_futex;
-# elif defined(BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE)
+# endif
+# elif defined(BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE)
+# if defined(BOOST_USE_TSX)
+using spinlock = spinlock_rtm< spinlock_ttas_adaptive >;
+# else
using spinlock = spinlock_ttas_adaptive;
+# endif
# else
+# if defined(BOOST_USE_TSX)
+using spinlock = spinlock_rtm< spinlock_ttas >;
+# else
using spinlock = spinlock_ttas;
+# endif
# endif
using spinlock_lock = std::unique_lock< spinlock >;
#endif
diff --git a/boost/fiber/detail/spinlock_rtm.hpp b/boost/fiber/detail/spinlock_rtm.hpp
new file mode 100644
index 0000000000..5cc4a5e9af
--- /dev/null
+++ b/boost/fiber/detail/spinlock_rtm.hpp
@@ -0,0 +1,126 @@
+
+// Copyright Oliver Kowalke 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_FIBERS_SPINLOCK_RTM_H
+#define BOOST_FIBERS_SPINLOCK_RTM_H
+
+#include <atomic>
+#include <chrono>
+#include <cmath>
+#include <random>
+#include <thread>
+
+#include <boost/fiber/detail/config.hpp>
+#include <boost/fiber/detail/cpu_relax.hpp>
+#include <boost/fiber/detail/rtm.hpp>
+#include <boost/fiber/detail/spinlock_status.hpp>
+
+namespace boost {
+namespace fibers {
+namespace detail {
+
+template< typename FBSplk >
+class spinlock_rtm {
+private:
+ FBSplk splk_{};
+
+public:
+ spinlock_rtm() = default;
+
+ spinlock_rtm( spinlock_rtm const&) = delete;
+ spinlock_rtm & operator=( spinlock_rtm const&) = delete;
+
+ void lock() noexcept {
+ static thread_local std::minstd_rand generator{ std::random_device{}() };
+ std::size_t collisions = 0 ;
+ for ( std::size_t retries = 0; retries < BOOST_FIBERS_RETRY_THRESHOLD; ++retries) {
+ std::uint32_t status;
+ if ( rtm_status::success == ( status = rtm_begin() ) ) {
+ // add lock to read-set
+ if ( spinlock_status::unlocked == splk_.state_.load( std::memory_order_relaxed) ) {
+ // lock is free, enter critical section
+ return;
+ }
+ // lock was acquired by another thread
+ // explicit abort of transaction with abort argument 'lock not free'
+ rtm_abort_lock_not_free();
+ }
+ // transaction aborted
+ if ( rtm_status::none != (status & rtm_status::may_retry) ||
+ rtm_status::none != (status & rtm_status::memory_conflict) ) {
+ // another logical processor conflicted with a memory address that was
+ // part or the read-/write-set
+ if ( BOOST_FIBERS_CONTENTION_WINDOW_THRESHOLD > collisions) {
+ std::uniform_int_distribution< std::size_t > distribution{
+ 0, static_cast< std::size_t >( 1) << (std::min)(collisions, static_cast< std::size_t >( BOOST_FIBERS_CONTENTION_WINDOW_THRESHOLD)) };
+ const std::size_t z = distribution( generator);
+ ++collisions;
+ for ( std::size_t i = 0; i < z; ++i) {
+ cpu_relax();
+ }
+ } else {
+ std::this_thread::yield();
+ }
+ } else if ( rtm_status::none != (status & rtm_status::explicit_abort) &&
+ rtm_status::none == (status & rtm_status::nested_abort) ) {
+ // another logical processor has acquired the lock and
+ // abort was not caused by a nested transaction
+ // wait till lock becomes free again
+ std::size_t count = 0;
+ while ( spinlock_status::locked == splk_.state_.load( std::memory_order_relaxed) ) {
+ if ( BOOST_FIBERS_SPIN_BEFORE_SLEEP0 > count) {
+ ++count;
+ cpu_relax();
+ } else if ( BOOST_FIBERS_SPIN_BEFORE_YIELD > count) {
+ ++count;
+ static constexpr std::chrono::microseconds us0{ 0 };
+ std::this_thread::sleep_for( us0);
+#if 0
+ using namespace std::chrono_literals;
+ std::this_thread::sleep_for( 0ms);
+#endif
+ } else {
+ std::this_thread::yield();
+ }
+ }
+ } else {
+ // transaction aborted due:
+ // - internal buffer to track transactional state overflowed
+ // - debug exception or breakpoint exception was hit
+ // - abort during execution of nested transactions (max nesting limit exceeded)
+ // -> use fallback path
+ break;
+ }
+ }
+ splk_.lock();
+ }
+
+ bool try_lock() noexcept {
+ if ( rtm_status::success != rtm_begin() ) {
+ return false;
+ }
+
+ // add lock to read-set
+ if ( spinlock_status::unlocked != splk_.state_.load( std::memory_order_relaxed) ) {
+ // lock was acquired by another thread
+ // explicit abort of transaction with abort argument 'lock not free'
+ rtm_abort_lock_not_free();
+ }
+ return true;
+ }
+
+ void unlock() noexcept {
+ if ( spinlock_status::unlocked == splk_.state_.load( std::memory_order_acquire) ) {
+ rtm_end();
+ } else {
+ splk_.unlock();
+ }
+ }
+};
+
+}}}
+
+#endif // BOOST_FIBERS_SPINLOCK_RTM_H
diff --git a/boost/fiber/detail/spinlock_status.hpp b/boost/fiber/detail/spinlock_status.hpp
new file mode 100644
index 0000000000..74f09e4acc
--- /dev/null
+++ b/boost/fiber/detail/spinlock_status.hpp
@@ -0,0 +1,21 @@
+
+// Copyright Oliver Kowalke 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_FIBERS_SPINLOCK_STATUS_H
+#define BOOST_FIBERS_SPINLOCK_STATUS_H
+
+namespace boost {
+namespace fibers {
+namespace detail {
+
+enum class spinlock_status {
+ locked = 0,
+ unlocked
+};
+
+}}}
+
+#endif // BOOST_FIBERS_SPINLOCK_STATUS_H
diff --git a/boost/fiber/detail/spinlock_ttas.hpp b/boost/fiber/detail/spinlock_ttas.hpp
index 380773ad6d..f3302ed17e 100644
--- a/boost/fiber/detail/spinlock_ttas.hpp
+++ b/boost/fiber/detail/spinlock_ttas.hpp
@@ -9,41 +9,37 @@
#include <atomic>
#include <chrono>
+#include <cmath>
#include <random>
#include <thread>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/cpu_relax.hpp>
+#include <boost/fiber/detail/spinlock_status.hpp>
// based on informations from:
// https://software.intel.com/en-us/articles/benefitting-power-and-performance-sleep-loops
// https://software.intel.com/en-us/articles/long-duration-spin-wait-loops-on-hyper-threading-technology-enabled-intel-processors
-#if BOOST_COMP_CLANG
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunused-private-field"
-#endif
-
namespace boost {
namespace fibers {
namespace detail {
class spinlock_ttas {
private:
- enum class spinlock_status {
- locked = 0,
- unlocked
- };
+ template< typename FBSplk >
+ friend class spinlock_rtm;
- std::atomic< spinlock_status > state_{ spinlock_status::unlocked };
+ std::atomic< spinlock_status > state_{ spinlock_status::unlocked };
public:
- spinlock_ttas() noexcept = default;
+ spinlock_ttas() = default;
spinlock_ttas( spinlock_ttas const&) = delete;
spinlock_ttas & operator=( spinlock_ttas const&) = delete;
void lock() noexcept {
+ static thread_local std::minstd_rand generator{ std::random_device{}() };
std::size_t collisions = 0 ;
for (;;) {
// avoid using multiple pause instructions for a delay of a specific cycle count
@@ -51,7 +47,7 @@ public:
// the cycle count can not guaranteed from one system to the next
// -> check the shared variable 'state_' in between each cpu_relax() to prevent
// unnecessarily long delays on some systems
- std::size_t tests = 0;
+ std::size_t retries = 0;
// test shared variable 'status_'
// first access to 'state_' -> chache miss
// sucessive acccess to 'state_' -> cache hit
@@ -59,21 +55,26 @@ public:
// cached 'state_' is invalidated -> cache miss
while ( spinlock_status::locked == state_.load( std::memory_order_relaxed) ) {
#if !defined(BOOST_FIBERS_SPIN_SINGLE_CORE)
- if ( BOOST_FIBERS_SPIN_MAX_TESTS > tests) {
- ++tests;
+ if ( BOOST_FIBERS_SPIN_BEFORE_SLEEP0 > retries) {
+ ++retries;
// give CPU a hint that this thread is in a "spin-wait" loop
// delays the next instruction's execution for a finite period of time (depends on processor family)
// the CPU is not under demand, parts of the pipeline are no longer being used
// -> reduces the power consumed by the CPU
// -> prevent pipeline stalls
cpu_relax();
- } else {
+ } else if ( BOOST_FIBERS_SPIN_BEFORE_YIELD > retries) {
// std::this_thread::sleep_for( 0us) has a fairly long instruction path length,
// combined with an expensive ring3 to ring 0 transition costing about 1000 cycles
// std::this_thread::sleep_for( 0us) lets give up this_thread the remaining part of its time slice
// if and only if a thread of equal or greater priority is ready to run
static constexpr std::chrono::microseconds us0{ 0 };
std::this_thread::sleep_for( us0);
+ } else {
+ // std::this_thread::yield() allows this_thread to give up the remaining part of its time slice,
+ // but only to another thread on the same processor
+ // instead of constant checking, a thread only checks if no other useful work is pending
+ std::this_thread::yield();
}
#else
std::this_thread::yield();
@@ -85,8 +86,8 @@ public:
// spinlock now contended
// utilize 'Binary Exponential Backoff' algorithm
// linear_congruential_engine is a random number engine based on Linear congruential generator (LCG)
- static thread_local std::minstd_rand generator;
- static std::uniform_int_distribution< std::size_t > distribution{ 0, static_cast< std::size_t >( 1) << collisions };
+ std::uniform_int_distribution< std::size_t > distribution{
+ 0, static_cast< std::size_t >( 1) << (std::min)(collisions, static_cast< std::size_t >( BOOST_FIBERS_CONTENTION_WINDOW_THRESHOLD)) };
const std::size_t z = distribution( generator);
++collisions;
for ( std::size_t i = 0; i < z; ++i) {
@@ -101,6 +102,10 @@ public:
}
}
+ bool try_lock() noexcept {
+ return spinlock_status::unlocked == state_.exchange( spinlock_status::locked, std::memory_order_acquire);
+ }
+
void unlock() noexcept {
state_.store( spinlock_status::unlocked, std::memory_order_release);
}
@@ -108,8 +113,4 @@ public:
}}}
-#if BOOST_COMP_CLANG
-#pragma clang diagnostic pop
-#endif
-
#endif // BOOST_FIBERS_SPINLOCK_TTAS_H
diff --git a/boost/fiber/detail/spinlock_ttas_adaptive.hpp b/boost/fiber/detail/spinlock_ttas_adaptive.hpp
index da044b6298..d1f8b73cf3 100644
--- a/boost/fiber/detail/spinlock_ttas_adaptive.hpp
+++ b/boost/fiber/detail/spinlock_ttas_adaptive.hpp
@@ -15,6 +15,7 @@
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/cpu_relax.hpp>
+#include <boost/fiber/detail/spinlock_status.hpp>
// based on informations from:
// https://software.intel.com/en-us/articles/benefitting-power-and-performance-sleep-loops
@@ -26,26 +27,28 @@ namespace detail {
class spinlock_ttas_adaptive {
private:
- enum class spinlock_status {
- locked = 0,
- unlocked
- };
+ template< typename FBSplk >
+ friend class spinlock_rtm;
- std::atomic< spinlock_status > state_{ spinlock_status::unlocked };
- std::atomic< std::size_t > tests_{ 0 };
+ std::atomic< spinlock_status > state_{ spinlock_status::unlocked };
+ std::atomic< std::size_t > retries_{ 0 };
public:
- spinlock_ttas_adaptive() noexcept = default;
+ spinlock_ttas_adaptive() = default;
spinlock_ttas_adaptive( spinlock_ttas_adaptive const&) = delete;
spinlock_ttas_adaptive & operator=( spinlock_ttas_adaptive const&) = delete;
void lock() noexcept {
+ static thread_local std::minstd_rand generator{ std::random_device{}() };
std::size_t collisions = 0 ;
for (;;) {
- std::size_t tests = 0;
- const std::size_t prev_tests = tests_.load( std::memory_order_relaxed);
- const std::size_t max_tests = (std::min)( static_cast< std::size_t >( BOOST_FIBERS_SPIN_MAX_TESTS), 2 * prev_tests + 10);
+ std::size_t retries = 0;
+ const std::size_t prev_retries = retries_.load( std::memory_order_relaxed);
+ const std::size_t max_relax_retries = (std::min)(
+ static_cast< std::size_t >( BOOST_FIBERS_SPIN_BEFORE_SLEEP0), 2 * prev_retries + 10);
+ const std::size_t max_sleep_retries = (std::min)(
+ static_cast< std::size_t >( BOOST_FIBERS_SPIN_BEFORE_YIELD), 2 * prev_retries + 10);
// avoid using multiple pause instructions for a delay of a specific cycle count
// the delay of cpu_relax() (pause on Intel) depends on the processor family
// the cycle count can not guaranteed from one system to the next
@@ -58,22 +61,27 @@ public:
// cached 'state_' is invalidated -> cache miss
while ( spinlock_status::locked == state_.load( std::memory_order_relaxed) ) {
#if !defined(BOOST_FIBERS_SPIN_SINGLE_CORE)
- if ( max_tests > tests) {
- ++tests;
+ if ( max_relax_retries > retries) {
+ ++retries;
// give CPU a hint that this thread is in a "spin-wait" loop
// delays the next instruction's execution for a finite period of time (depends on processor family)
// the CPU is not under demand, parts of the pipeline are no longer being used
// -> reduces the power consumed by the CPU
// -> prevent pipeline stalls
cpu_relax();
- } else {
- ++tests;
+ } else if ( max_sleep_retries > retries) {
+ ++retries;
// std::this_thread::sleep_for( 0us) has a fairly long instruction path length,
// combined with an expensive ring3 to ring 0 transition costing about 1000 cycles
// std::this_thread::sleep_for( 0us) lets give up this_thread the remaining part of its time slice
// if and only if a thread of equal or greater priority is ready to run
static constexpr std::chrono::microseconds us0{ 0 };
std::this_thread::sleep_for( us0);
+ } else {
+ // std::this_thread::yield() allows this_thread to give up the remaining part of its time slice,
+ // but only to another thread on the same processor
+ // instead of constant checking, a thread only checks if no other useful work is pending
+ std::this_thread::yield();
}
#else
std::this_thread::yield();
@@ -85,8 +93,8 @@ public:
// spinlock now contended
// utilize 'Binary Exponential Backoff' algorithm
// linear_congruential_engine is a random number engine based on Linear congruential generator (LCG)
- static thread_local std::minstd_rand generator;
- static std::uniform_int_distribution< std::size_t > distribution{ 0, static_cast< std::size_t >( 1) << collisions };
+ std::uniform_int_distribution< std::size_t > distribution{
+ 0, static_cast< std::size_t >( 1) << (std::min)(collisions, static_cast< std::size_t >( BOOST_FIBERS_CONTENTION_WINDOW_THRESHOLD)) };
const std::size_t z = distribution( generator);
++collisions;
for ( std::size_t i = 0; i < z; ++i) {
@@ -95,13 +103,17 @@ public:
cpu_relax();
}
} else {
- tests_.store( prev_tests + (tests - prev_tests) / 8, std::memory_order_relaxed);
+ retries_.store( prev_retries + (retries - prev_retries) / 8, std::memory_order_relaxed);
// success, thread has acquired the lock
break;
}
}
}
+ bool try_lock() noexcept {
+ return spinlock_status::unlocked == state_.exchange( spinlock_status::locked, std::memory_order_acquire);
+ }
+
void unlock() noexcept {
state_.store( spinlock_status::unlocked, std::memory_order_release);
}
diff --git a/boost/fiber/detail/spinlock_ttas_adaptive_futex.hpp b/boost/fiber/detail/spinlock_ttas_adaptive_futex.hpp
index 61ab47691e..0f0b191e67 100644
--- a/boost/fiber/detail/spinlock_ttas_adaptive_futex.hpp
+++ b/boost/fiber/detail/spinlock_ttas_adaptive_futex.hpp
@@ -26,21 +26,28 @@ namespace detail {
class spinlock_ttas_adaptive_futex {
private:
- std::atomic< std::int32_t > value_{ 0 };
- std::atomic< std::int32_t > tests_{ 0 };
+ template< typename FBSplk >
+ friend class spinlock_rtm;
+
+ std::atomic< std::int32_t > value_{ 0 };
+ std::atomic< std::int32_t > retries_{ 0 };
public:
- spinlock_ttas_adaptive_futex() noexcept = default;
+ spinlock_ttas_adaptive_futex() = default;
spinlock_ttas_adaptive_futex( spinlock_ttas_adaptive_futex const&) = delete;
spinlock_ttas_adaptive_futex & operator=( spinlock_ttas_adaptive_futex const&) = delete;
void lock() noexcept {
- std::int32_t collisions = 0, tests = 0, expected = 0;
- const std::int32_t prev_tests = tests_.load( std::memory_order_relaxed);
- const std::int32_t max_tests = (std::min)( static_cast< std::int32_t >( BOOST_FIBERS_SPIN_MAX_TESTS), 2 * prev_tests + 10);
+ static thread_local std::minstd_rand generator{ std::random_device{}() };
+ std::int32_t collisions = 0, retries = 0, expected = 0;
+ const std::int32_t prev_retries = retries_.load( std::memory_order_relaxed);
+ const std::int32_t max_relax_retries = (std::min)(
+ static_cast< std::int32_t >( BOOST_FIBERS_SPIN_BEFORE_SLEEP0), 2 * prev_retries + 10);
+ const std::int32_t max_sleep_retries = (std::min)(
+ static_cast< std::int32_t >( BOOST_FIBERS_SPIN_BEFORE_YIELD), 2 * prev_retries + 10);
// after max. spins or collisions suspend via futex
- while ( max_tests > tests && BOOST_FIBERS_SPIN_MAX_COLLISIONS > collisions) {
+ while ( retries++ < BOOST_FIBERS_RETRY_THRESHOLD) {
// avoid using multiple pause instructions for a delay of a specific cycle count
// the delay of cpu_relax() (pause on Intel) depends on the processor family
// the cycle count can not guaranteed from one system to the next
@@ -52,26 +59,39 @@ public:
// if 'value_' was released by other fiber
// cached 'value_' is invalidated -> cache miss
if ( 0 != ( expected = value_.load( std::memory_order_relaxed) ) ) {
- ++tests;
#if !defined(BOOST_FIBERS_SPIN_SINGLE_CORE)
- // give CPU a hint that this thread is in a "spin-wait" loop
- // delays the next instruction's execution for a finite period of time (depends on processor family)
- // the CPU is not under demand, parts of the pipeline are no longer being used
- // -> reduces the power consumed by the CPU
- // -> prevent pipeline stalls
- cpu_relax();
+ if ( max_relax_retries > retries) {
+ // give CPU a hint that this thread is in a "spin-wait" loop
+ // delays the next instruction's execution for a finite period of time (depends on processor family)
+ // the CPU is not under demand, parts of the pipeline are no longer being used
+ // -> reduces the power consumed by the CPU
+ // -> prevent pipeline stalls
+ cpu_relax();
+ } else if ( max_sleep_retries > retries) {
+ // std::this_thread::sleep_for( 0us) has a fairly long instruction path length,
+ // combined with an expensive ring3 to ring 0 transition costing about 1000 cycles
+ // std::this_thread::sleep_for( 0us) lets give up this_thread the remaining part of its time slice
+ // if and only if a thread of equal or greater priority is ready to run
+ static constexpr std::chrono::microseconds us0{ 0 };
+ std::this_thread::sleep_for( us0);
+ } else {
+ // std::this_thread::yield() allows this_thread to give up the remaining part of its time slice,
+ // but only to another thread on the same processor
+ // instead of constant checking, a thread only checks if no other useful work is pending
+ std::this_thread::yield();
+ }
#else
// std::this_thread::yield() allows this_thread to give up the remaining part of its time slice,
// but only to another thread on the same processor
// instead of constant checking, a thread only checks if no other useful work is pending
std::this_thread::yield();
#endif
- } else if ( ! value_.compare_exchange_strong( expected, 1, std::memory_order_acquire, std::memory_order_release) ) {
+ } else if ( ! value_.compare_exchange_strong( expected, 1, std::memory_order_acquire) ) {
// spinlock now contended
// utilize 'Binary Exponential Backoff' algorithm
// linear_congruential_engine is a random number engine based on Linear congruential generator (LCG)
- static thread_local std::minstd_rand generator;
- static std::uniform_int_distribution< std::int32_t > distribution{ 0, static_cast< std::int32_t >( 1) << collisions };
+ std::uniform_int_distribution< std::int32_t > distribution{
+ 0, static_cast< std::int32_t >( 1) << (std::min)(collisions, static_cast< std::int32_t >( BOOST_FIBERS_CONTENTION_WINDOW_THRESHOLD)) };
const std::int32_t z = distribution( generator);
++collisions;
for ( std::int32_t i = 0; i < z; ++i) {
@@ -81,7 +101,7 @@ public:
}
} else {
// success, lock acquired
- tests_.store( prev_tests + (tests - prev_tests) / 8, std::memory_order_relaxed);
+ retries_.store( prev_retries + (retries - prev_retries) / 8, std::memory_order_relaxed);
return;
}
}
@@ -95,7 +115,12 @@ public:
expected = value_.exchange( 2, std::memory_order_acquire);
}
// success, lock acquired
- tests_.store( prev_tests + (tests - prev_tests) / 8, std::memory_order_relaxed);
+ retries_.store( prev_retries + (retries - prev_retries) / 8, std::memory_order_relaxed);
+ }
+
+ bool try_lock() noexcept {
+ std::int32_t expected = 0;
+ return value_.compare_exchange_strong( expected, 1, std::memory_order_acquire);
}
void unlock() noexcept {
diff --git a/boost/fiber/detail/spinlock_ttas_futex.hpp b/boost/fiber/detail/spinlock_ttas_futex.hpp
index a427b73ba5..fd30c4120e 100644
--- a/boost/fiber/detail/spinlock_ttas_futex.hpp
+++ b/boost/fiber/detail/spinlock_ttas_futex.hpp
@@ -8,6 +8,7 @@
#define BOOST_FIBERS_spinlock_ttas_futex_FUTEX_H
#include <atomic>
+#include <cmath>
#include <random>
#include <thread>
@@ -25,18 +26,22 @@ namespace detail {
class spinlock_ttas_futex {
private:
- std::atomic< std::int32_t > value_{ 0 };
+ template< typename FBSplk >
+ friend class spinlock_rtm;
+
+ std::atomic< std::int32_t > value_{ 0 };
public:
- spinlock_ttas_futex() noexcept = default;
+ spinlock_ttas_futex() = default;
spinlock_ttas_futex( spinlock_ttas_futex const&) = delete;
spinlock_ttas_futex & operator=( spinlock_ttas_futex const&) = delete;
void lock() noexcept {
- std::int32_t collisions = 0, tests = 0, expected = 0;
+ static thread_local std::minstd_rand generator{ std::random_device{}() };
+ std::int32_t collisions = 0, retries = 0, expected = 0;
// after max. spins or collisions suspend via futex
- while ( BOOST_FIBERS_SPIN_MAX_TESTS > tests && BOOST_FIBERS_SPIN_MAX_COLLISIONS > collisions) {
+ while ( retries++ < BOOST_FIBERS_RETRY_THRESHOLD) {
// avoid using multiple pause instructions for a delay of a specific cycle count
// the delay of cpu_relax() (pause on Intel) depends on the processor family
// the cycle count can not guaranteed from one system to the next
@@ -48,26 +53,39 @@ public:
// if 'value_' was released by other fiber
// cached 'value_' is invalidated -> cache miss
if ( 0 != ( expected = value_.load( std::memory_order_relaxed) ) ) {
- ++tests;
#if !defined(BOOST_FIBERS_SPIN_SINGLE_CORE)
- // give CPU a hint that this thread is in a "spin-wait" loop
- // delays the next instruction's execution for a finite period of time (depends on processor family)
- // the CPU is not under demand, parts of the pipeline are no longer being used
- // -> reduces the power consumed by the CPU
- // -> prevent pipeline stalls
- cpu_relax();
+ if ( BOOST_FIBERS_SPIN_BEFORE_SLEEP0 > retries) {
+ // give CPU a hint that this thread is in a "spin-wait" loop
+ // delays the next instruction's execution for a finite period of time (depends on processor family)
+ // the CPU is not under demand, parts of the pipeline are no longer being used
+ // -> reduces the power consumed by the CPU
+ // -> prevent pipeline stalls
+ cpu_relax();
+ } else if ( BOOST_FIBERS_SPIN_BEFORE_YIELD > retries) {
+ // std::this_thread::sleep_for( 0us) has a fairly long instruction path length,
+ // combined with an expensive ring3 to ring 0 transition costing about 1000 cycles
+ // std::this_thread::sleep_for( 0us) lets give up this_thread the remaining part of its time slice
+ // if and only if a thread of equal or greater priority is ready to run
+ static constexpr std::chrono::microseconds us0{ 0 };
+ std::this_thread::sleep_for( us0);
+ } else {
+ // std::this_thread::yield() allows this_thread to give up the remaining part of its time slice,
+ // but only to another thread on the same processor
+ // instead of constant checking, a thread only checks if no other useful work is pending
+ std::this_thread::yield();
+ }
#else
// std::this_thread::yield() allows this_thread to give up the remaining part of its time slice,
// but only to another thread on the same processor
// instead of constant checking, a thread only checks if no other useful work is pending
std::this_thread::yield();
#endif
- } else if ( ! value_.compare_exchange_strong( expected, 1, std::memory_order_acquire, std::memory_order_release) ) {
+ } else if ( ! value_.compare_exchange_strong( expected, 1, std::memory_order_acquire) ) {
// spinlock now contended
// utilize 'Binary Exponential Backoff' algorithm
// linear_congruential_engine is a random number engine based on Linear congruential generator (LCG)
- static thread_local std::minstd_rand generator;
- static std::uniform_int_distribution< std::int32_t > distribution{ 0, static_cast< std::int32_t >( 1) << collisions };
+ std::uniform_int_distribution< std::int32_t > distribution{
+ 0, static_cast< std::int32_t >( 1) << (std::min)(collisions, static_cast< std::int32_t >( BOOST_FIBERS_CONTENTION_WINDOW_THRESHOLD)) };
const std::int32_t z = distribution( generator);
++collisions;
for ( std::int32_t i = 0; i < z; ++i) {
@@ -91,6 +109,11 @@ public:
}
}
+ bool try_lock() noexcept {
+ std::int32_t expected = 0;
+ return value_.compare_exchange_strong( expected, 1, std::memory_order_acquire);
+ }
+
void unlock() noexcept {
if ( 1 != value_.fetch_sub( 1, std::memory_order_acquire) ) {
value_.store( 0, std::memory_order_release);
diff --git a/boost/fiber/detail/wrap.hpp b/boost/fiber/detail/wrap.hpp
deleted file mode 100644
index 558de6bd94..0000000000
--- a/boost/fiber/detail/wrap.hpp
+++ /dev/null
@@ -1,131 +0,0 @@
-
-// Copyright Oliver Kowalke 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_FIBER_DETAIL_WRAP_H
-#define BOOST_FIBER_DETAIL_WRAP_H
-
-#include <type_traits>
-
-#include <boost/config.hpp>
-#if defined(BOOST_NO_CXX17_STD_INVOKE)
-#include <boost/context/detail/invoke.hpp>
-#endif
-#if (BOOST_EXECUTION_CONTEXT==1)
-# include <boost/context/execution_context.hpp>
-#else
-# include <boost/context/continuation.hpp>
-#endif
-
-#include <boost/fiber/detail/config.hpp>
-#include <boost/fiber/detail/data.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace fibers {
-namespace detail {
-
-#if (BOOST_EXECUTION_CONTEXT==1)
-template< typename Fn1, typename Fn2, typename Tpl >
-class wrapper {
-private:
- typename std::decay< Fn1 >::type fn1_;
- typename std::decay< Fn2 >::type fn2_;
- typename std::decay< Tpl >::type tpl_;
- boost::context::execution_context ctx_;
-
-public:
- wrapper( Fn1 && fn1, Fn2 && fn2, Tpl && tpl,
- boost::context::execution_context const& ctx) :
- fn1_{ std::move( fn1) },
- fn2_{ std::move( fn2) },
- tpl_{ std::move( tpl) },
- ctx_{ ctx } {
- }
-
- wrapper( wrapper const&) = delete;
- wrapper & operator=( wrapper const&) = delete;
-
- wrapper( wrapper && other) = default;
- wrapper & operator=( wrapper && other) = default;
-
- void operator()( void * vp) {
-#if defined(BOOST_NO_CXX17_STD_INVOKE)
- boost::context::detail::invoke( std::move( fn1_), fn2_, tpl_, ctx_, vp);
-#else
- std::invoke( std::move( fn1_), fn2_, tpl_, ctx_, vp);
-#endif
- }
-};
-
-template< typename Fn1, typename Fn2, typename Tpl >
-wrapper< Fn1, Fn2, Tpl >
-wrap( Fn1 && fn1, Fn2 && fn2, Tpl && tpl,
- boost::context::execution_context const& ctx) {
- return wrapper< Fn1, Fn2, Tpl >{
- std::forward< Fn1 >( fn1),
- std::forward< Fn2 >( fn2),
- std::forward< Tpl >( tpl),
- ctx };
-}
-#else
-template< typename Fn1, typename Fn2, typename Tpl >
-class wrapper {
-private:
- typename std::decay< Fn1 >::type fn1_;
- typename std::decay< Fn2 >::type fn2_;
- typename std::decay< Tpl >::type tpl_;
-
-public:
- wrapper( Fn1 && fn1, Fn2 && fn2, Tpl && tpl) :
- fn1_{ std::move( fn1) },
- fn2_{ std::move( fn2) },
- tpl_{ std::move( tpl) } {
- }
-
- wrapper( wrapper const&) = delete;
- wrapper & operator=( wrapper const&) = delete;
-
- wrapper( wrapper && other) = default;
- wrapper & operator=( wrapper && other) = default;
-
- boost::context::continuation
- operator()( boost::context::continuation && c) {
-#if defined(BOOST_NO_CXX17_STD_INVOKE)
- return boost::context::detail::invoke(
- std::move( fn1_),
- fn2_,
- tpl_,
- std::forward< boost::context::continuation >( c) );
-#else
- return std::invoke(
- std::move( fn1_),
- fn2_,
- tpl_,
- std::forward< boost::context::continuation >( c) );
-#endif
- }
-};
-
-template< typename Fn1, typename Fn2, typename Tpl >
-wrapper< Fn1, Fn2, Tpl >
-wrap( Fn1 && fn1, Fn2 && fn2, Tpl && tpl) {
- return wrapper< Fn1, Fn2, Tpl >{
- std::forward< Fn1 >( fn1),
- std::forward< Fn2 >( fn2),
- std::forward< Tpl >( tpl) };
-}
-#endif
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-#include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_FIBER_DETAIL_WRAP_H
diff --git a/boost/fiber/fiber.hpp b/boost/fiber/fiber.hpp
index 1508a9b5a6..eb10487c66 100644
--- a/boost/fiber/fiber.hpp
+++ b/boost/fiber/fiber.hpp
@@ -15,6 +15,7 @@
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/intrusive_ptr.hpp>
+#include <boost/predef.h>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/disable_overload.hpp>
@@ -52,41 +53,59 @@ public:
fiber() = default;
template< typename Fn,
- typename ... Args,
- typename = detail::disable_overload< fiber, Fn >
+ typename ... Arg,
+ typename = detail::disable_overload< fiber, Fn >,
+ typename = detail::disable_overload< launch, Fn >,
+ typename = detail::disable_overload< std::allocator_arg_t, Fn >
>
- fiber( Fn && fn, Args && ... args) :
+#if BOOST_COMP_GNUC < 50000000
+ fiber( Fn && fn, Arg && ... arg) :
+#else
+ fiber( Fn && fn, Arg ... arg) :
+#endif
fiber{ launch::post,
std::allocator_arg, default_stack(),
- std::forward< Fn >( fn), std::forward< Args >( args) ... } {
+ std::forward< Fn >( fn), std::forward< Arg >( arg) ... } {
}
template< typename Fn,
- typename ... Args,
+ typename ... Arg,
typename = detail::disable_overload< fiber, Fn >
>
- fiber( launch policy, Fn && fn, Args && ... args) :
+#if BOOST_COMP_GNUC < 50000000
+ fiber( launch policy, Fn && fn, Arg && ... arg) :
+#else
+ fiber( launch policy, Fn && fn, Arg ... arg) :
+#endif
fiber{ policy,
std::allocator_arg, default_stack(),
- std::forward< Fn >( fn), std::forward< Args >( args) ... } {
+ std::forward< Fn >( fn), std::forward< Arg >( arg) ... } {
}
template< typename StackAllocator,
typename Fn,
- typename ... Args
+ typename ... Arg
>
- fiber( std::allocator_arg_t, StackAllocator salloc, Fn && fn, Args && ... args) :
+#if BOOST_COMP_GNUC < 50000000
+ fiber( std::allocator_arg_t, StackAllocator salloc, Fn && fn, Arg && ... arg) :
+#else
+ fiber( std::allocator_arg_t, StackAllocator salloc, Fn && fn, Arg ... arg) :
+#endif
fiber{ launch::post,
std::allocator_arg, salloc,
- std::forward< Fn >( fn), std::forward< Args >( args) ... } {
+ std::forward< Fn >( fn), std::forward< Arg >( arg) ... } {
}
template< typename StackAllocator,
typename Fn,
- typename ... Args
+ typename ... Arg
>
- fiber( launch policy, std::allocator_arg_t, StackAllocator salloc, Fn && fn, Args && ... args) :
- impl_{ make_worker_context( policy, salloc, std::forward< Fn >( fn), std::forward< Args >( args) ... ) } {
+#if BOOST_COMP_GNUC < 50000000
+ fiber( launch policy, std::allocator_arg_t, StackAllocator salloc, Fn && fn, Arg && ... arg) :
+#else
+ fiber( launch policy, std::allocator_arg_t, StackAllocator salloc, Fn && fn, Arg ... arg) :
+#endif
+ impl_{ make_worker_context( policy, salloc, std::forward< Fn >( fn), std::forward< Arg >( arg) ... ) } {
start_();
}
@@ -108,7 +127,7 @@ public:
if ( joinable() ) {
std::terminate();
}
- if ( this == & other) {
+ if ( BOOST_UNLIKELY( this == & other) ) {
return * this;
}
impl_.swap( other.impl_);
diff --git a/boost/fiber/fss.hpp b/boost/fiber/fss.hpp
index f65d7353b3..0a321bb661 100644
--- a/boost/fiber/fss.hpp
+++ b/boost/fiber/fss.hpp
@@ -37,8 +37,8 @@ private:
fn{ fn_ } {
}
- void operator()( void* data) {
- if ( fn) {
+ void operator()( void * data) {
+ if ( BOOST_LIKELY( nullptr != fn) ) {
fn( static_cast< T * >( data) );
}
}
@@ -91,7 +91,7 @@ public:
void reset( T * t) {
T * c = get();
- if ( c != t) {
+ if ( BOOST_LIKELY( c != t) ) {
context::active()->set_fss_data(
this, cleanup_fn_, t, true);
}
diff --git a/boost/fiber/future/async.hpp b/boost/fiber/future/async.hpp
index e68b2c28fa..9601e8cdfe 100644
--- a/boost/fiber/future/async.hpp
+++ b/boost/fiber/future/async.hpp
@@ -30,7 +30,7 @@ future<
>::type( typename std::decay< Args >::type ... )
>::type
>
-async( Fn && fn, Args && ... args) {
+async( Fn && fn, Args ... args) {
typedef typename std::result_of<
typename std::decay< Fn >::type( typename std::decay< Args >::type ... )
>::type result_type;
@@ -51,7 +51,7 @@ future<
>::type( typename std::decay< Args >::type ...)
>::type
>
-async( Policy policy, Fn && fn, Args && ... args) {
+async( Policy policy, Fn && fn, Args ... args) {
typedef typename std::result_of<
typename std::decay< Fn >::type( typename std::decay< Args >::type ... )
>::type result_type;
@@ -72,7 +72,7 @@ future<
>::type( typename std::decay< Args >::type ... )
>::type
>
-async( Policy policy, std::allocator_arg_t, StackAllocator salloc, Fn && fn, Args && ... args) {
+async( Policy policy, std::allocator_arg_t, StackAllocator salloc, Fn && fn, Args ... args) {
typedef typename std::result_of<
typename std::decay< Fn >::type( typename std::decay< Args >::type ... )
>::type result_type;
@@ -94,7 +94,7 @@ future<
>::type( typename std::decay< Args >::type ... )
>::type
>
-async( Policy policy, std::allocator_arg_t, StackAllocator salloc, Allocator alloc, Fn && fn, Args && ... args) {
+async( Policy policy, std::allocator_arg_t, StackAllocator salloc, Allocator alloc, Fn && fn, Args ... args) {
typedef typename std::result_of<
typename std::decay< Fn >::type( typename std::decay< Args >::type ... )
>::type result_type;
diff --git a/boost/fiber/future/detail/shared_state.hpp b/boost/fiber/future/detail/shared_state.hpp
index 898fdaffd4..28e0e3cfb9 100644
--- a/boost/fiber/future/detail/shared_state.hpp
+++ b/boost/fiber/future/detail/shared_state.hpp
@@ -62,7 +62,7 @@ protected:
void set_exception_( std::exception_ptr except, std::unique_lock< mutex > & lk) {
BOOST_ASSERT( lk.owns_lock() );
- if ( ready_) {
+ if ( BOOST_UNLIKELY( ready_) ) {
throw promise_already_satisfied();
}
except_ = except;
@@ -161,19 +161,19 @@ private:
void set_value_( R const& value, std::unique_lock< mutex > & lk) {
BOOST_ASSERT( lk.owns_lock() );
- if ( ready_) {
+ if ( BOOST_UNLIKELY( ready_) ) {
throw promise_already_satisfied{};
}
- ::new ( static_cast< void * >( std::addressof( storage_) ) ) R{ value };
+ ::new ( static_cast< void * >( std::addressof( storage_) ) ) R( value );
mark_ready_and_notify_( lk);
}
void set_value_( R && value, std::unique_lock< mutex > & lk) {
BOOST_ASSERT( lk.owns_lock() );
- if ( ready_) {
+ if ( BOOST_UNLIKELY( ready_) ) {
throw promise_already_satisfied{};
}
- ::new ( static_cast< void * >( std::addressof( storage_) ) ) R{ std::move( value) };
+ ::new ( static_cast< void * >( std::addressof( storage_) ) ) R( std::move( value) );
mark_ready_and_notify_( lk);
}
@@ -223,7 +223,7 @@ private:
void set_value_( R & value, std::unique_lock< mutex > & lk) {
BOOST_ASSERT( lk.owns_lock() );
- if ( ready_) {
+ if ( BOOST_UNLIKELY( ready_) ) {
throw promise_already_satisfied();
}
value_ = std::addressof( value);
@@ -266,7 +266,7 @@ private:
inline
void set_value_( std::unique_lock< mutex > & lk) {
BOOST_ASSERT( lk.owns_lock() );
- if ( ready_) {
+ if ( BOOST_UNLIKELY( ready_) ) {
throw promise_already_satisfied();
}
mark_ready_and_notify_( lk);
diff --git a/boost/fiber/future/detail/task_object.hpp b/boost/fiber/future/detail/task_object.hpp
index 3a48929a58..abb4c8d877 100644
--- a/boost/fiber/future/detail/task_object.hpp
+++ b/boost/fiber/future/detail/task_object.hpp
@@ -16,6 +16,7 @@
#if defined(BOOST_NO_CXX17_STD_APPLY)
#include <boost/context/detail/apply.hpp>
#endif
+#include <boost/core/pointer_traits.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/future/detail/task_base.hpp>
@@ -68,15 +69,17 @@ public:
typename base_type::ptr_type reset() override final {
typedef std::allocator_traits< allocator_type > traity_type;
+ typedef pointer_traits< typename traity_type::pointer> ptrait_type;
typename traity_type::pointer ptr{ traity_type::allocate( alloc_, 1) };
+ typename ptrait_type::element_type* p = ptrait_type::to_address(ptr);
try {
- traity_type::construct( alloc_, ptr, alloc_, std::move( fn_) );
+ traity_type::construct( alloc_, p, alloc_, std::move( fn_) );
} catch (...) {
traity_type::deallocate( alloc_, ptr, 1);
throw;
}
- return { convert( ptr) };
+ return { p };
}
protected:
@@ -134,15 +137,17 @@ public:
typename base_type::ptr_type reset() override final {
typedef std::allocator_traits< allocator_type > traity_type;
+ typedef pointer_traits< typename traity_type::pointer> ptrait_type;
typename traity_type::pointer ptr{ traity_type::allocate( alloc_, 1) };
+ typename ptrait_type::element_type* p = ptrait_type::to_address(ptr);
try {
- traity_type::construct( alloc_, ptr, alloc_, std::move( fn_) );
+ traity_type::construct( alloc_, p, alloc_, std::move( fn_) );
} catch (...) {
traity_type::deallocate( alloc_, ptr, 1);
throw;
}
- return { convert( ptr) };
+ return { p };
}
protected:
diff --git a/boost/fiber/future/future.hpp b/boost/fiber/future/future.hpp
index 5d4ad78ab5..2191080d69 100644
--- a/boost/fiber/future/future.hpp
+++ b/boost/fiber/future/future.hpp
@@ -46,14 +46,14 @@ struct future_base {
}
future_base & operator=( future_base const& other) noexcept {
- if ( this != & other) {
+ if ( BOOST_LIKELY( this != & other) ) {
state_ = other.state_;
}
return * this;
}
future_base & operator=( future_base && other) noexcept {
- if ( this != & other) {
+ if ( BOOST_LIKELY( this != & other) ) {
state_ = other.state_;
other.state_.reset();
}
@@ -65,14 +65,14 @@ struct future_base {
}
std::exception_ptr get_exception_ptr() {
- if ( ! valid() ) {
+ if ( BOOST_UNLIKELY( ! valid() ) ) {
throw future_uninitialized{};
}
return state_->get_exception_ptr();
}
void wait() const {
- if ( ! valid() ) {
+ if ( BOOST_UNLIKELY( ! valid() ) ) {
throw future_uninitialized{};
}
state_->wait();
@@ -80,7 +80,7 @@ struct future_base {
template< typename Rep, typename Period >
future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const {
- if ( ! valid() ) {
+ if ( BOOST_UNLIKELY( ! valid() ) ) {
throw future_uninitialized{};
}
return state_->wait_for( timeout_duration);
@@ -88,7 +88,7 @@ struct future_base {
template< typename Clock, typename Duration >
future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const {
- if ( ! valid() ) {
+ if ( BOOST_UNLIKELY( ! valid() ) ) {
throw future_uninitialized{};
}
return state_->wait_until( timeout_time);
@@ -131,7 +131,7 @@ public:
}
future & operator=( future && other) noexcept {
- if ( this != & other) {
+ if ( BOOST_LIKELY( this != & other) ) {
base_type::operator=( std::move( other) );
}
return * this;
@@ -140,7 +140,7 @@ public:
shared_future< R > share();
R get() {
- if ( ! base_type::valid() ) {
+ if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
throw future_uninitialized{};
}
typename base_type::ptr_type tmp{};
@@ -180,7 +180,7 @@ public:
}
future & operator=( future && other) noexcept {
- if ( this != & other) {
+ if ( BOOST_LIKELY( this != & other) ) {
base_type::operator=( std::move( other) );
}
return * this;
@@ -189,7 +189,7 @@ public:
shared_future< R & > share();
R & get() {
- if ( ! base_type::valid() ) {
+ if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
throw future_uninitialized{};
}
typename base_type::ptr_type tmp{};
@@ -231,7 +231,7 @@ public:
inline
future & operator=( future && other) noexcept {
- if ( this != & other) {
+ if ( BOOST_LIKELY( this != & other) ) {
base_type::operator=( std::move( other) );
}
return * this;
@@ -241,7 +241,7 @@ public:
inline
void get() {
- if ( ! base_type::valid() ) {
+ if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
throw future_uninitialized{};
}
base_type::ptr_type tmp{};
@@ -284,14 +284,14 @@ public:
}
shared_future & operator=( shared_future const& other) noexcept {
- if ( this != & other) {
+ if ( BOOST_LIKELY( this != & other) ) {
base_type::operator=( other);
}
return * this;
}
shared_future & operator=( shared_future && other) noexcept {
- if ( this != & other) {
+ if ( BOOST_LIKELY( this != & other) ) {
base_type::operator=( std::move( other) );
}
return * this;
@@ -303,7 +303,7 @@ public:
}
R const& get() const {
- if ( ! valid() ) {
+ if ( BOOST_UNLIKELY( ! valid() ) ) {
throw future_uninitialized{};
}
return base_type::state_->get();
@@ -343,14 +343,14 @@ public:
}
shared_future & operator=( shared_future const& other) noexcept {
- if ( this != & other) {
+ if ( BOOST_LIKELY( this != & other) ) {
base_type::operator=( other);
}
return * this;
}
shared_future & operator=( shared_future && other) noexcept {
- if ( this != & other) {
+ if ( BOOST_LIKELY( this != & other) ) {
base_type::operator=( std::move( other) );
}
return * this;
@@ -362,7 +362,7 @@ public:
}
R & get() const {
- if ( ! valid() ) {
+ if ( BOOST_UNLIKELY( ! valid() ) ) {
throw future_uninitialized{};
}
return base_type::state_->get();
@@ -406,7 +406,7 @@ public:
inline
shared_future & operator=( shared_future const& other) noexcept {
- if ( this != & other) {
+ if ( BOOST_LIKELY( this != & other) ) {
base_type::operator=( other);
}
return * this;
@@ -414,7 +414,7 @@ public:
inline
shared_future & operator=( shared_future && other) noexcept {
- if ( this != & other) {
+ if ( BOOST_LIKELY( this != & other) ) {
base_type::operator=( std::move( other) );
}
return * this;
@@ -428,7 +428,7 @@ public:
inline
void get() const {
- if ( ! valid() ) {
+ if ( BOOST_UNLIKELY( ! valid() ) ) {
throw future_uninitialized{};
}
base_type::state_->get();
@@ -445,7 +445,7 @@ public:
template< typename R >
shared_future< R >
future< R >::share() {
- if ( ! base_type::valid() ) {
+ if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
throw future_uninitialized{};
}
return shared_future< R >{ std::move( * this) };
@@ -454,7 +454,7 @@ future< R >::share() {
template< typename R >
shared_future< R & >
future< R & >::share() {
- if ( ! base_type::valid() ) {
+ if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
throw future_uninitialized{};
}
return shared_future< R & >{ std::move( * this) };
@@ -463,7 +463,7 @@ future< R & >::share() {
inline
shared_future< void >
future< void >::share() {
- if ( ! base_type::valid() ) {
+ if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
throw future_uninitialized{};
}
return shared_future< void >{ std::move( * this) };
diff --git a/boost/fiber/future/packaged_task.hpp b/boost/fiber/future/packaged_task.hpp
index 31838ee41f..c8b10d43e0 100644
--- a/boost/fiber/future/packaged_task.hpp
+++ b/boost/fiber/future/packaged_task.hpp
@@ -14,7 +14,6 @@
#include <boost/config.hpp>
-#include <boost/fiber/detail/convert.hpp>
#include <boost/fiber/detail/disable_overload.hpp>
#include <boost/fiber/exceptions.hpp>
#include <boost/fiber/future/detail/task_base.hpp>
@@ -57,16 +56,18 @@ public:
typedef std::allocator_traits<
typename object_type::allocator_type
> traits_type;
+ typedef pointer_traits< typename traits_type::pointer > ptrait_type;
typename object_type::allocator_type a{ alloc };
typename traits_type::pointer ptr{ traits_type::allocate( a, 1) };
+ typename ptrait_type::element_type* p = ptrait_type::to_address(ptr);
try {
- traits_type::construct( a, ptr, a, std::forward< Fn >( fn) );
+ traits_type::construct( a, p, a, std::forward< Fn >( fn) );
} catch (...) {
traits_type::deallocate( a, ptr, 1);
throw;
}
- task_.reset( convert( ptr) );
+ task_.reset(p);
}
~packaged_task() {
@@ -85,7 +86,7 @@ public:
}
packaged_task & operator=( packaged_task && other) noexcept {
- if ( this != & other) {
+ if ( BOOST_LIKELY( this != & other) ) {
packaged_task tmp{ std::move( other) };
swap( tmp);
}
@@ -105,7 +106,7 @@ public:
if ( obtained_) {
throw future_already_retrieved{};
}
- if ( ! valid() ) {
+ if ( BOOST_UNLIKELY( ! valid() ) ) {
throw packaged_task_uninitialized{};
}
obtained_ = true;
@@ -114,14 +115,14 @@ public:
}
void operator()( Args ... args) {
- if ( ! valid() ) {
+ if ( BOOST_UNLIKELY( ! valid() ) ) {
throw packaged_task_uninitialized{};
}
task_->run( std::forward< Args >( args) ... );
}
void reset() {
- if ( ! valid() ) {
+ if ( BOOST_UNLIKELY( ! valid() ) ) {
throw packaged_task_uninitialized{};
}
packaged_task tmp;
diff --git a/boost/fiber/future/promise.hpp b/boost/fiber/future/promise.hpp
index 83ba63fb23..661c8b0480 100644
--- a/boost/fiber/future/promise.hpp
+++ b/boost/fiber/future/promise.hpp
@@ -12,8 +12,8 @@
#include <utility>
#include <boost/config.hpp>
+#include <boost/core/pointer_traits.hpp>
-#include <boost/fiber/detail/convert.hpp>
#include <boost/fiber/exceptions.hpp>
#include <boost/fiber/future/detail/shared_state.hpp>
#include <boost/fiber/future/detail/shared_state_object.hpp>
@@ -38,16 +38,18 @@ struct promise_base {
promise_base( std::allocator_arg_t, Allocator alloc) {
typedef detail::shared_state_object< R, Allocator > object_type;
typedef std::allocator_traits< typename object_type::allocator_type > traits_type;
+ typedef pointer_traits< typename traits_type::pointer > ptrait_type;
typename object_type::allocator_type a{ alloc };
typename traits_type::pointer ptr{ traits_type::allocate( a, 1) };
+ typename ptrait_type::element_type* p = ptrait_type::to_address(ptr);
try {
- traits_type::construct( a, ptr, a);
+ traits_type::construct( a, p, a);
} catch (...) {
traits_type::deallocate( a, ptr, 1);
throw;
}
- future_.reset( convert( ptr) );
+ future_.reset(p);
}
~promise_base() {
@@ -66,7 +68,7 @@ struct promise_base {
}
promise_base & operator=( promise_base && other) noexcept {
- if ( this != & other) {
+ if ( BOOST_LIKELY( this != & other) ) {
promise_base tmp{ std::move( other) };
swap( tmp);
}
@@ -74,10 +76,10 @@ struct promise_base {
}
future< R > get_future() {
- if ( obtained_) {
+ if ( BOOST_UNLIKELY( obtained_) ) {
throw future_already_retrieved{};
}
- if ( ! future_) {
+ if ( BOOST_UNLIKELY( ! future_) ) {
throw promise_uninitialized{};
}
obtained_ = true;
@@ -90,7 +92,7 @@ struct promise_base {
}
void set_exception( std::exception_ptr p) {
- if ( ! future_) {
+ if ( BOOST_UNLIKELY( ! future_) ) {
throw promise_uninitialized{};
}
future_->set_exception( p);
@@ -119,14 +121,14 @@ public:
promise & operator=( promise && other) = default;
void set_value( R const& value) {
- if ( ! base_type::future_) {
+ if ( BOOST_UNLIKELY( ! base_type::future_) ) {
throw promise_uninitialized{};
}
base_type::future_->set_value( value);
}
void set_value( R && value) {
- if ( ! base_type::future_) {
+ if ( BOOST_UNLIKELY( ! base_type::future_) ) {
throw promise_uninitialized{};
}
base_type::future_->set_value( std::move( value) );
@@ -160,7 +162,7 @@ public:
promise & operator=( promise && other) noexcept = default;
void set_value( R & value) {
- if ( ! base_type::future_) {
+ if ( BOOST_UNLIKELY( ! base_type::future_) ) {
throw promise_uninitialized{};
}
base_type::future_->set_value( value);
@@ -195,7 +197,7 @@ public:
inline
void set_value() {
- if ( ! base_type::future_) {
+ if ( BOOST_UNLIKELY( ! base_type::future_) ) {
throw promise_uninitialized{};
}
base_type::future_->set_value();
diff --git a/boost/fiber/numa/pin_thread.hpp b/boost/fiber/numa/pin_thread.hpp
new file mode 100644
index 0000000000..c8d48395c6
--- /dev/null
+++ b/boost/fiber/numa/pin_thread.hpp
@@ -0,0 +1,33 @@
+
+// Copyright Oliver Kowalke 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_FIBERS_NUMA_PIN_THREAD_H
+#define BOOST_FIBERS_NUMA_PIN_THREAD_H
+
+#include <cstdint>
+
+#include <boost/config.hpp>
+
+#include <boost/fiber/detail/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace fibers {
+namespace numa {
+
+BOOST_FIBERS_DECL
+void pin_thread( std::uint32_t);
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_FIBERS_NUMA_PIN_THREAD_H
diff --git a/boost/fiber/numa/topology.hpp b/boost/fiber/numa/topology.hpp
new file mode 100644
index 0000000000..7b67fad288
--- /dev/null
+++ b/boost/fiber/numa/topology.hpp
@@ -0,0 +1,46 @@
+
+// Copyright Oliver Kowalke 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_FIBERS_NUMA_TOPOLOGY_H
+#define BOOST_FIBERS_NUMA_TOPOLOGY_H
+
+#include <cstdint>
+#include <set>
+#include <vector>
+
+#include <boost/config.hpp>
+
+#include <boost/fiber/detail/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace fibers {
+namespace numa {
+
+struct node {
+ std::uint32_t id;
+ std::set< std::uint32_t > logical_cpus;
+ std::vector< std::uint32_t > distance;
+};
+
+inline
+bool operator<( node const& lhs, node const& rhs) noexcept {
+ return lhs.id < rhs.id;
+}
+
+BOOST_FIBERS_DECL
+std::vector< node > topology();
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_FIBERS_NUMA_TOPOLOGY_H
diff --git a/boost/fiber/operations.hpp b/boost/fiber/operations.hpp
index 95ab9ba452..22b58562da 100644
--- a/boost/fiber/operations.hpp
+++ b/boost/fiber/operations.hpp
@@ -10,6 +10,7 @@
#include <boost/config.hpp>
+#include <boost/fiber/algo/algorithm.hpp>
#include <boost/fiber/context.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/convert.hpp>
@@ -36,19 +37,22 @@ void yield() noexcept {
template< typename Clock, typename Duration >
void sleep_until( std::chrono::time_point< Clock, Duration > const& sleep_time_) {
std::chrono::steady_clock::time_point sleep_time = boost::fibers::detail::convert( sleep_time_);
- fibers::context::active()->wait_until( sleep_time);
+ fibers::context * active_ctx = fibers::context::active();
+ active_ctx->twstatus.store( static_cast< std::intptr_t >( 0), std::memory_order_release);
+ active_ctx->wait_until( sleep_time);
}
template< typename Rep, typename Period >
void sleep_for( std::chrono::duration< Rep, Period > const& timeout_duration) {
- fibers::context::active()->wait_until(
- std::chrono::steady_clock::now() + timeout_duration);
+ fibers::context * active_ctx = fibers::context::active();
+ active_ctx->twstatus.store( static_cast< std::intptr_t >( 0), std::memory_order_release);
+ active_ctx->wait_until( std::chrono::steady_clock::now() + timeout_duration);
}
template< typename PROPS >
PROPS & properties() {
fibers::fiber_properties * props = fibers::context::active()->get_properties();
- if ( ! props) {
+ if ( BOOST_LIKELY( nullptr == props) ) {
// props could be nullptr if the thread's main fiber has not yet
// yielded (not yet passed through algorithm_with_properties::
// awakened()). Address that by yielding right now.
@@ -76,9 +80,7 @@ bool has_ready_fibers() noexcept {
template< typename SchedAlgo, typename ... Args >
void use_scheduling_algorithm( Args && ... args) noexcept {
boost::fibers::context::active()->get_scheduler()
- ->set_algo(
- std::unique_ptr< SchedAlgo >(
- new SchedAlgo( std::forward< Args >( args) ... ) ) );
+ ->set_algo( new SchedAlgo( std::forward< Args >( args) ... ) );
}
}}
diff --git a/boost/fiber/properties.hpp b/boost/fiber/properties.hpp
index 09ac7405d6..2f8b7a008d 100644
--- a/boost/fiber/properties.hpp
+++ b/boost/fiber/properties.hpp
@@ -28,7 +28,7 @@ class context;
namespace algo {
-struct algorithm;
+class algorithm;
}
diff --git a/boost/fiber/scheduler.hpp b/boost/fiber/scheduler.hpp
index 4a5f0dab8c..accedf03d7 100644
--- a/boost/fiber/scheduler.hpp
+++ b/boost/fiber/scheduler.hpp
@@ -13,11 +13,7 @@
#include <vector>
#include <boost/config.hpp>
-#if (BOOST_EXECUTION_CONTEXT==1)
-# include <boost/context/execution_context.hpp>
-#else
-# include <boost/context/continuation.hpp>
-#endif
+#include <boost/context/continuation.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/intrusive/set.hpp>
@@ -90,7 +86,7 @@ private:
detail::spinlock remote_ready_splk_{};
remote_ready_queue_type remote_ready_queue_{};
#endif
- alignas(cache_alignment) std::unique_ptr< algo::algorithm > algo_;
+ algo::algorithm::ptr_t algo_;
// sleep-queue contains context' which have been called
// scheduler::wait_until()
sleep_queue_type sleep_queue_{};
@@ -126,15 +122,9 @@ public:
void schedule_from_remote( context *) noexcept;
#endif
-#if (BOOST_EXECUTION_CONTEXT==1)
- void dispatch() noexcept;
-
- void terminate( detail::spinlock_lock &, context *) noexcept;
-#else
boost::context::continuation dispatch() noexcept;
boost::context::continuation terminate( detail::spinlock_lock &, context *) noexcept;
-#endif
void yield( context *) noexcept;
@@ -149,7 +139,7 @@ public:
bool has_ready_fibers() const noexcept;
- void set_algo( std::unique_ptr< algo::algorithm >) noexcept;
+ void set_algo( algo::algorithm::ptr_t) noexcept;
void attach_main_context( context *) noexcept;
diff --git a/boost/fiber/type.hpp b/boost/fiber/type.hpp
index 065d22fccb..d9ab0a94d7 100644
--- a/boost/fiber/type.hpp
+++ b/boost/fiber/type.hpp
@@ -29,7 +29,6 @@
#include <boost/fiber/detail/decay_copy.hpp>
#include <boost/fiber/detail/fss.hpp>
#include <boost/fiber/detail/spinlock.hpp>
-#include <boost/fiber/detail/wrap.hpp>
#include <boost/fiber/exceptions.hpp>
#include <boost/fiber/fixedsize_stack.hpp>
#include <boost/fiber/properties.hpp>
diff --git a/boost/fiber/unbuffered_channel.hpp b/boost/fiber/unbuffered_channel.hpp
index 38a2d6111e..1474299ded 100644
--- a/boost/fiber/unbuffered_channel.hpp
+++ b/boost/fiber/unbuffered_channel.hpp
@@ -38,7 +38,7 @@ public:
private:
typedef context::wait_queue_t wait_queue_type;
- struct alignas(cache_alignment) slot {
+ struct slot {
value_type value;
context * ctx;
@@ -54,12 +54,12 @@ private:
};
// shared cacheline
- alignas(cache_alignment) std::atomic< slot * > slot_{ nullptr };
+ std::atomic< slot * > slot_{ nullptr };
// shared cacheline
- alignas(cache_alignment) std::atomic_bool closed_{ false };
- alignas(cache_alignment) mutable detail::spinlock splk_producers_{};
+ std::atomic_bool closed_{ false };
+ mutable detail::spinlock splk_producers_{};
wait_queue_type waiting_producers_{};
- alignas( cache_alignment) mutable detail::spinlock splk_consumers_{};
+ mutable detail::spinlock splk_consumers_{};
wait_queue_type waiting_consumers_{};
char pad_[cacheline_length];
@@ -98,13 +98,6 @@ public:
~unbuffered_channel() {
close();
- slot * s = nullptr;
- if ( nullptr != ( s = try_pop_() ) ) {
- BOOST_ASSERT( nullptr != s);
- BOOST_ASSERT( nullptr != s->ctx);
- // value will be destructed in the context of the waiting fiber
- context::active()->schedule( s->ctx);
- }
}
unbuffered_channel( unbuffered_channel const&) = delete;
@@ -122,14 +115,46 @@ public:
while ( ! waiting_producers_.empty() ) {
context * producer_ctx = & waiting_producers_.front();
waiting_producers_.pop_front();
- active_ctx->schedule( producer_ctx);
+ std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+ if ( producer_ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+ // notify before timeout
+ intrusive_ptr_release( producer_ctx);
+ // notify context
+ active_ctx->schedule( producer_ctx);
+ } else if ( static_cast< std::intptr_t >( 0) == expected) {
+ // no timed-wait op.
+ // notify context
+ active_ctx->schedule( producer_ctx);
+ } else {
+ // timed-wait op.
+ // expected == -1: notify after timeout, same timed-wait op.
+ // expected == <any>: notify after timeout, another timed-wait op. was already started
+ intrusive_ptr_release( producer_ctx);
+ // re-schedule next
+ }
}
// notify all waiting consumers
detail::spinlock_lock lk2{ splk_consumers_ };
while ( ! waiting_consumers_.empty() ) {
context * consumer_ctx = & waiting_consumers_.front();
waiting_consumers_.pop_front();
- active_ctx->schedule( consumer_ctx);
+ std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+ if ( consumer_ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+ // notify before timeout
+ intrusive_ptr_release( consumer_ctx);
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ } else if ( static_cast< std::intptr_t >( 0) == expected) {
+ // no timed-wait op.
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ } else {
+ // timed-wait op.
+ // expected == -1: notify after timeout, same timed-wait op.
+ // expected == <any>: notify after timeout, another timed-wait op. was already started
+ intrusive_ptr_release( consumer_ctx);
+ // re-schedule next
+ }
}
}
@@ -137,16 +162,34 @@ public:
context * active_ctx = context::active();
slot s{ value, active_ctx };
for (;;) {
- if ( is_closed() ) {
+ if ( BOOST_UNLIKELY( is_closed() ) ) {
return channel_op_status::closed;
}
if ( try_push_( & s) ) {
detail::spinlock_lock lk{ splk_consumers_ };
// notify one waiting consumer
- if ( ! waiting_consumers_.empty() ) {
+ while ( ! waiting_consumers_.empty() ) {
context * consumer_ctx = & waiting_consumers_.front();
waiting_consumers_.pop_front();
- active_ctx->schedule( consumer_ctx);
+ std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+ if ( consumer_ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+ // notify before timeout
+ intrusive_ptr_release( consumer_ctx);
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ break;
+ } else if ( static_cast< std::intptr_t >( 0) == expected) {
+ // no timed-wait op.
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ break;
+ } else {
+ // timed-wait op.
+ // expected == -1: notify after timeout, same timed-wait op.
+ // expected == <any>: notify after timeout, another timed-wait op. was already started
+ intrusive_ptr_release( consumer_ctx);
+ // re-schedule next
+ }
}
// suspend till value has been consumed
active_ctx->suspend( lk);
@@ -154,13 +197,14 @@ public:
return channel_op_status::success;
} else {
detail::spinlock_lock lk{ splk_producers_ };
- if ( is_closed() ) {
+ if ( BOOST_UNLIKELY( is_closed() ) ) {
return channel_op_status::closed;
}
if ( is_empty_() ) {
continue;
}
active_ctx->wait_link( waiting_producers_);
+ active_ctx->twstatus.store( static_cast< std::intptr_t >( 0), std::memory_order_release);
// suspend this producer
active_ctx->suspend( lk);
// resumed, slot mabye free
@@ -172,16 +216,34 @@ public:
context * active_ctx = context::active();
slot s{ std::move( value), active_ctx };
for (;;) {
- if ( is_closed() ) {
+ if ( BOOST_UNLIKELY( is_closed() ) ) {
return channel_op_status::closed;
}
if ( try_push_( & s) ) {
detail::spinlock_lock lk{ splk_consumers_ };
// notify one waiting consumer
- if ( ! waiting_consumers_.empty() ) {
+ while ( ! waiting_consumers_.empty() ) {
context * consumer_ctx = & waiting_consumers_.front();
waiting_consumers_.pop_front();
- active_ctx->schedule( consumer_ctx);
+ std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+ if ( consumer_ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+ // notify before timeout
+ intrusive_ptr_release( consumer_ctx);
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ break;
+ } else if ( static_cast< std::intptr_t >( 0) == expected) {
+ // no timed-wait op.
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ break;
+ } else {
+ // timed-wait op.
+ // expected == -1: notify after timeout, same timed-wait op.
+ // expected == <any>: notify after timeout, another timed-wait op. was already started
+ intrusive_ptr_release( consumer_ctx);
+ // re-schedule next
+ }
}
// suspend till value has been consumed
active_ctx->suspend( lk);
@@ -189,13 +251,14 @@ public:
return channel_op_status::success;
} else {
detail::spinlock_lock lk{ splk_producers_ };
- if ( is_closed() ) {
+ if ( BOOST_UNLIKELY( is_closed() ) ) {
return channel_op_status::closed;
}
if ( is_empty_() ) {
continue;
}
active_ctx->wait_link( waiting_producers_);
+ active_ctx->twstatus.store( static_cast< std::intptr_t >( 0), std::memory_order_release);
// suspend this producer
active_ctx->suspend( lk);
// resumed, slot mabye free
@@ -224,18 +287,38 @@ public:
slot s{ value, active_ctx };
std::chrono::steady_clock::time_point timeout_time = detail::convert( timeout_time_);
for (;;) {
- if ( is_closed() ) {
+ if ( BOOST_UNLIKELY( is_closed() ) ) {
return channel_op_status::closed;
}
if ( try_push_( & s) ) {
detail::spinlock_lock lk{ splk_consumers_ };
// notify one waiting consumer
- if ( ! waiting_consumers_.empty() ) {
+ while ( ! waiting_consumers_.empty() ) {
context * consumer_ctx = & waiting_consumers_.front();
waiting_consumers_.pop_front();
- active_ctx->schedule( consumer_ctx);
+ std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+ if ( consumer_ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+ // notify before timeout
+ intrusive_ptr_release( consumer_ctx);
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ break;
+ } else if ( static_cast< std::intptr_t >( 0) == expected) {
+ // no timed-wait op.
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ break;
+ } else {
+ // timed-wait op.
+ // expected == -1: notify after timeout, same timed-wait op.
+ // expected == <any>: notify after timeout, another timed-wait op. was already started
+ intrusive_ptr_release( consumer_ctx);
+ // re-schedule next
+ }
}
// suspend this producer
+ intrusive_ptr_add_ref( active_ctx);
+ active_ctx->twstatus.store( reinterpret_cast< std::intptr_t >( this), std::memory_order_release);
if ( ! active_ctx->wait_until( timeout_time, lk) ) {
// clear slot
slot * nil_slot = nullptr, * own_slot = & s;
@@ -247,13 +330,15 @@ public:
return channel_op_status::success;
} else {
detail::spinlock_lock lk{ splk_producers_ };
- if ( is_closed() ) {
+ if ( BOOST_UNLIKELY( is_closed() ) ) {
return channel_op_status::closed;
}
if ( is_empty_() ) {
continue;
}
active_ctx->wait_link( waiting_producers_);
+ intrusive_ptr_add_ref( active_ctx);
+ active_ctx->twstatus.store( reinterpret_cast< std::intptr_t >( this), std::memory_order_release);
// suspend this producer
if ( ! active_ctx->wait_until( timeout_time, lk) ) {
// relock local lk
@@ -274,18 +359,38 @@ public:
slot s{ std::move( value), active_ctx };
std::chrono::steady_clock::time_point timeout_time = detail::convert( timeout_time_);
for (;;) {
- if ( is_closed() ) {
+ if ( BOOST_UNLIKELY( is_closed() ) ) {
return channel_op_status::closed;
}
if ( try_push_( & s) ) {
detail::spinlock_lock lk{ splk_consumers_ };
// notify one waiting consumer
- if ( ! waiting_consumers_.empty() ) {
+ while ( ! waiting_consumers_.empty() ) {
context * consumer_ctx = & waiting_consumers_.front();
waiting_consumers_.pop_front();
- active_ctx->schedule( consumer_ctx);
+ std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+ if ( consumer_ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+ // notify before timeout
+ intrusive_ptr_release( consumer_ctx);
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ break;
+ } else if ( static_cast< std::intptr_t >( 0) == expected) {
+ // no timed-wait op.
+ // notify context
+ active_ctx->schedule( consumer_ctx);
+ break;
+ } else {
+ // timed-wait op.
+ // expected == -1: notify after timeout, same timed-wait op.
+ // expected == <any>: notify after timeout, another timed-wait op. was already started
+ intrusive_ptr_release( consumer_ctx);
+ // re-schedule next
+ }
}
// suspend this producer
+ intrusive_ptr_add_ref( active_ctx);
+ active_ctx->twstatus.store( reinterpret_cast< std::intptr_t >( this), std::memory_order_release);
if ( ! active_ctx->wait_until( timeout_time, lk) ) {
// clear slot
slot * nil_slot = nullptr, * own_slot = & s;
@@ -297,13 +402,15 @@ public:
return channel_op_status::success;
} else {
detail::spinlock_lock lk{ splk_producers_ };
- if ( is_closed() ) {
+ if ( BOOST_UNLIKELY( is_closed() ) ) {
return channel_op_status::closed;
}
if ( is_empty_() ) {
continue;
}
active_ctx->wait_link( waiting_producers_);
+ intrusive_ptr_add_ref( active_ctx);
+ active_ctx->twstatus.store( reinterpret_cast< std::intptr_t >( this), std::memory_order_release);
// suspend this producer
if ( ! active_ctx->wait_until( timeout_time, lk) ) {
// relock local lk
@@ -325,27 +432,45 @@ public:
{
detail::spinlock_lock lk{ splk_producers_ };
// notify one waiting producer
- if ( ! waiting_producers_.empty() ) {
+ while ( ! waiting_producers_.empty() ) {
context * producer_ctx = & waiting_producers_.front();
waiting_producers_.pop_front();
lk.unlock();
- active_ctx->schedule( producer_ctx);
+ std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+ if ( producer_ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+ // notify before timeout
+ intrusive_ptr_release( producer_ctx);
+ // notify context
+ active_ctx->schedule( producer_ctx);
+ break;
+ } else if ( static_cast< std::intptr_t >( 0) == expected) {
+ // no timed-wait op.
+ // notify context
+ active_ctx->schedule( producer_ctx);
+ break;
+ } else {
+ // timed-wait op.
+ // expected == -1: notify after timeout, same timed-wait op.
+ // expected == <any>: notify after timeout, another timed-wait op. was already started
+ intrusive_ptr_release( producer_ctx);
+ // re-schedule next
+ }
}
}
- // consume value
value = std::move( s->value);
- // resume suspended producer
+ // notify context
active_ctx->schedule( s->ctx);
return channel_op_status::success;
} else {
detail::spinlock_lock lk{ splk_consumers_ };
- if ( is_closed() ) {
+ if ( BOOST_UNLIKELY( is_closed() ) ) {
return channel_op_status::closed;
}
if ( ! is_empty_() ) {
continue;
}
active_ctx->wait_link( waiting_consumers_);
+ active_ctx->twstatus.store( static_cast< std::intptr_t >( 0), std::memory_order_release);
// suspend this consumer
active_ctx->suspend( lk);
// resumed, slot mabye set
@@ -361,21 +486,39 @@ public:
{
detail::spinlock_lock lk{ splk_producers_ };
// notify one waiting producer
- if ( ! waiting_producers_.empty() ) {
+ while ( ! waiting_producers_.empty() ) {
context * producer_ctx = & waiting_producers_.front();
waiting_producers_.pop_front();
lk.unlock();
- active_ctx->schedule( producer_ctx);
+ std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+ if ( producer_ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+ // notify before timeout
+ intrusive_ptr_release( producer_ctx);
+ // notify context
+ active_ctx->schedule( producer_ctx);
+ break;
+ } else if ( static_cast< std::intptr_t >( 0) == expected) {
+ // no timed-wait op.
+ // notify context
+ active_ctx->schedule( producer_ctx);
+ break;
+ } else {
+ // timed-wait op.
+ // expected == -1: notify after timeout, same timed-wait op.
+ // expected == <any>: notify after timeout, another timed-wait op. was already started
+ intrusive_ptr_release( producer_ctx);
+ // re-schedule next
+ }
}
}
// consume value
- value_type value{ std::move( s->value) };
- // resume suspended producer
+ value_type value = std::move( s->value);
+ // notify context
active_ctx->schedule( s->ctx);
return std::move( value);
} else {
detail::spinlock_lock lk{ splk_consumers_ };
- if ( is_closed() ) {
+ if ( BOOST_UNLIKELY( is_closed() ) ) {
throw fiber_error{
std::make_error_code( std::errc::operation_not_permitted),
"boost fiber: channel is closed" };
@@ -384,6 +527,7 @@ public:
continue;
}
active_ctx->wait_link( waiting_consumers_);
+ active_ctx->twstatus.store( static_cast< std::intptr_t >( 0), std::memory_order_release);
// suspend this consumer
active_ctx->suspend( lk);
// resumed, slot mabye set
@@ -409,27 +553,47 @@ public:
{
detail::spinlock_lock lk{ splk_producers_ };
// notify one waiting producer
- if ( ! waiting_producers_.empty() ) {
+ while ( ! waiting_producers_.empty() ) {
context * producer_ctx = & waiting_producers_.front();
waiting_producers_.pop_front();
lk.unlock();
- active_ctx->schedule( producer_ctx);
+ std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+ if ( producer_ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+ // notify before timeout
+ intrusive_ptr_release( producer_ctx);
+ // notify context
+ active_ctx->schedule( producer_ctx);
+ break;
+ } else if ( static_cast< std::intptr_t >( 0) == expected) {
+ // no timed-wait op.
+ // notify context
+ active_ctx->schedule( producer_ctx);
+ break;
+ } else {
+ // timed-wait op.
+ // expected == -1: notify after timeout, same timed-wait op.
+ // expected == <any>: notify after timeout, another timed-wait op. was already started
+ intrusive_ptr_release( producer_ctx);
+ // re-schedule next
+ }
}
}
// consume value
value = std::move( s->value);
- // resume suspended producer
+ // notify context
active_ctx->schedule( s->ctx);
return channel_op_status::success;
} else {
detail::spinlock_lock lk{ splk_consumers_ };
- if ( is_closed() ) {
+ if ( BOOST_UNLIKELY( is_closed() ) ) {
return channel_op_status::closed;
}
if ( ! is_empty_() ) {
continue;
}
active_ctx->wait_link( waiting_consumers_);
+ intrusive_ptr_add_ref( active_ctx);
+ active_ctx->twstatus.store( reinterpret_cast< std::intptr_t >( this), std::memory_order_release);
// suspend this consumer
if ( ! active_ctx->wait_until( timeout_time, lk) ) {
// relock local lk
diff --git a/boost/functional/hash/hash.hpp b/boost/functional/hash/hash.hpp
index 76c4897ebe..b461f5f0d7 100644
--- a/boost/functional/hash/hash.hpp
+++ b/boost/functional/hash/hash.hpp
@@ -107,6 +107,16 @@ namespace boost
boost::hash_detail::enable_hash_value {};
#endif
+#if !defined(BOOST_NO_CXX11_CHAR16_T)
+ template <> struct basic_numbers<char16_t> :
+ boost::hash_detail::enable_hash_value {};
+#endif
+
+#if !defined(BOOST_NO_CXX11_CHAR32_T)
+ template <> struct basic_numbers<char32_t> :
+ boost::hash_detail::enable_hash_value {};
+#endif
+
// long_numbers is defined like this to allow for separate
// specialization for long_long and int128_type, in case
// they conflict.
@@ -456,6 +466,12 @@ namespace boost
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
BOOST_HASH_SPECIALIZE(wchar_t)
#endif
+#if !defined(BOOST_NO_CXX11_CHAR16_T)
+ BOOST_HASH_SPECIALIZE(char16_t)
+#endif
+#if !defined(BOOST_NO_CXX11_CHAR32_T)
+ BOOST_HASH_SPECIALIZE(char32_t)
+#endif
BOOST_HASH_SPECIALIZE(short)
BOOST_HASH_SPECIALIZE(unsigned short)
BOOST_HASH_SPECIALIZE(int)
@@ -471,6 +487,12 @@ namespace boost
#if !defined(BOOST_NO_STD_WSTRING) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
BOOST_HASH_SPECIALIZE_REF(std::wstring)
#endif
+#if !defined(BOOST_NO_CXX11_CHAR16_T)
+ BOOST_HASH_SPECIALIZE_REF(std::basic_string<char16_t>)
+#endif
+#if !defined(BOOST_NO_CXX11_CHAR32_T)
+ BOOST_HASH_SPECIALIZE_REF(std::basic_string<char32_t>)
+#endif
#if !defined(BOOST_NO_LONG_LONG)
BOOST_HASH_SPECIALIZE(boost::long_long_type)
diff --git a/boost/fusion/container/deque/deque_fwd.hpp b/boost/fusion/container/deque/deque_fwd.hpp
index ebbeb4c1d7..5b8ea56fc5 100644
--- a/boost/fusion/container/deque/deque_fwd.hpp
+++ b/boost/fusion/container/deque/deque_fwd.hpp
@@ -23,8 +23,7 @@
# endif
#endif
-// MSVC variadics at this point in time is not ready yet (ICE!)
-#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1900))
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
# if defined(BOOST_FUSION_HAS_VARIADIC_DEQUE)
# undef BOOST_FUSION_HAS_VARIADIC_DEQUE
# endif
diff --git a/boost/fusion/container/map/map_fwd.hpp b/boost/fusion/container/map/map_fwd.hpp
index 992396730c..18e445b03e 100644
--- a/boost/fusion/container/map/map_fwd.hpp
+++ b/boost/fusion/container/map/map_fwd.hpp
@@ -23,8 +23,7 @@
# endif
#endif
-// MSVC variadics at this point in time is not ready yet (ICE!)
-#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1900))
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
# if defined(BOOST_FUSION_HAS_VARIADIC_MAP)
# undef BOOST_FUSION_HAS_VARIADIC_MAP
# endif
diff --git a/boost/fusion/container/vector/detail/config.hpp b/boost/fusion/container/vector/detail/config.hpp
index 2a7aea64a8..718b2d7954 100644
--- a/boost/fusion/container/vector/detail/config.hpp
+++ b/boost/fusion/container/vector/detail/config.hpp
@@ -27,8 +27,7 @@
# endif
#endif
-// Sometimes, MSVC 12 shows compile error with std::size_t of template parameter.
-#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1800))
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
# if defined(BOOST_FUSION_HAS_VARIADIC_VECTOR)
# undef BOOST_FUSION_HAS_VARIADIC_VECTOR
# endif
diff --git a/boost/fusion/include/adapt_adt_named.cpp b/boost/fusion/include/std_array.hpp
index 8ccdf0777e..ceb815ba96 100644
--- a/boost/fusion/include/adapt_adt_named.cpp
+++ b/boost/fusion/include/std_array.hpp
@@ -1,13 +1,13 @@
/*=============================================================================
- Copyright (c) 2001-2009 Joel de Guzman
+ Copyright (c) 2017 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)
==============================================================================*/
-#if !defined(FUSION_INCLUDE_ADAPT_ADT_NAMED)
-#define FUSION_INCLUDE_ADAPT_ADT_NAMED
+#if !defined(FUSION_INCLUDE_STD_ARRAY)
+#define FUSION_INCLUDE_STD_ARRAY
#include <boost/fusion/support/config.hpp>
-#include <boost/fusion/adapted/adt/adapt_adt_named.hpp>
+#include <boost/fusion/adapted/std_array.hpp>
#endif
diff --git a/boost/geometry/algorithms/correct.hpp b/boost/geometry/algorithms/correct.hpp
index 5d3b6939af..a572d921d5 100644
--- a/boost/geometry/algorithms/correct.hpp
+++ b/boost/geometry/algorithms/correct.hpp
@@ -5,6 +5,10 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -61,7 +65,8 @@ namespace detail { namespace correct
template <typename Geometry>
struct correct_nop
{
- static inline void apply(Geometry& )
+ template <typename Strategy>
+ static inline void apply(Geometry& , Strategy const& )
{}
};
@@ -104,8 +109,8 @@ struct correct_box_loop<Box, DimensionCount, DimensionCount>
template <typename Box>
struct correct_box
{
-
- static inline void apply(Box& box)
+ template <typename Strategy>
+ static inline void apply(Box& box, Strategy const& )
{
// Currently only for Cartesian coordinates
// (or spherical without crossing dateline)
@@ -119,18 +124,12 @@ struct correct_box
// Close a ring, if not closed
-template <typename Ring, typename Predicate>
+template <typename Ring, template <typename> class Predicate>
struct correct_ring
{
typedef typename point_type<Ring>::type point_type;
typedef typename coordinate_type<Ring>::type coordinate_type;
- typedef typename strategy::area::services::default_strategy
- <
- typename cs_tag<point_type>::type,
- point_type
- >::type strategy_type;
-
typedef detail::area::ring_area
<
order_as_direction<geometry::point_order<Ring>::value>::value,
@@ -138,7 +137,8 @@ struct correct_ring
> ring_area_type;
- static inline void apply(Ring& r)
+ template <typename Strategy>
+ static inline void apply(Ring& r, Strategy const& strategy)
{
// Check close-ness
if (boost::size(r) > 2)
@@ -158,10 +158,10 @@ struct correct_ring
}
}
// Check area
- Predicate predicate;
- typedef typename default_area_result<Ring>::type area_result_type;
- area_result_type const zero = area_result_type();
- if (predicate(ring_area_type::apply(r, strategy_type()), zero))
+ typedef typename Strategy::return_type area_result_type;
+ Predicate<area_result_type> predicate;
+ area_result_type const zero = 0;
+ if (predicate(ring_area_type::apply(r, strategy), zero))
{
std::reverse(boost::begin(r), boost::end(r));
}
@@ -174,15 +174,15 @@ template <typename Polygon>
struct correct_polygon
{
typedef typename ring_type<Polygon>::type ring_type;
- typedef typename default_area_result<Polygon>::type area_result_type;
-
- static inline void apply(Polygon& poly)
+
+ template <typename Strategy>
+ static inline void apply(Polygon& poly, Strategy const& strategy)
{
correct_ring
<
ring_type,
- std::less<area_result_type>
- >::apply(exterior_ring(poly));
+ std::less
+ >::apply(exterior_ring(poly), strategy);
typename interior_return_type<Polygon>::type
rings = interior_rings(poly);
@@ -192,8 +192,8 @@ struct correct_polygon
correct_ring
<
ring_type,
- std::greater<area_result_type>
- >::apply(*it);
+ std::greater
+ >::apply(*it, strategy);
}
}
};
@@ -237,7 +237,7 @@ struct correct<Ring, ring_tag>
: detail::correct::correct_ring
<
Ring,
- std::less<typename default_area_result<Ring>::type>
+ std::less
>
{};
@@ -281,29 +281,36 @@ namespace resolve_variant {
template <typename Geometry>
struct correct
{
- static inline void apply(Geometry& geometry)
+ template <typename Strategy>
+ static inline void apply(Geometry& geometry, Strategy const& strategy)
{
concepts::check<Geometry const>();
- dispatch::correct<Geometry>::apply(geometry);
+ dispatch::correct<Geometry>::apply(geometry, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct correct<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
+ template <typename Strategy>
struct visitor: boost::static_visitor<void>
{
+ Strategy const& m_strategy;
+
+ visitor(Strategy const& strategy): m_strategy(strategy) {}
+
template <typename Geometry>
void operator()(Geometry& geometry) const
{
- correct<Geometry>::apply(geometry);
+ correct<Geometry>::apply(geometry, m_strategy);
}
};
+ template <typename Strategy>
static inline void
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry)
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry, Strategy const& strategy)
{
- boost::apply_visitor(visitor(), geometry);
+ boost::apply_visitor(visitor<Strategy>(strategy), geometry);
}
};
@@ -325,7 +332,37 @@ struct correct<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
inline void correct(Geometry& geometry)
{
- resolve_variant::correct<Geometry>::apply(geometry);
+ typedef typename point_type<Geometry>::type point_type;
+
+ typedef typename strategy::area::services::default_strategy
+ <
+ typename cs_tag<point_type>::type,
+ point_type
+ >::type strategy_type;
+
+ resolve_variant::correct<Geometry>::apply(geometry, strategy_type());
+}
+
+/*!
+\brief Corrects a geometry
+\details Corrects a geometry: all rings which are wrongly oriented with respect
+ to their expected orientation are reversed. To all rings which do not have a
+ closing point and are typed as they should have one, the first point is
+ appended. Also boxes can be corrected.
+\ingroup correct
+\tparam Geometry \tparam_geometry
+\tparam Strategy \tparam_strategy{Area}
+\param geometry \param_geometry which will be corrected if necessary
+\param strategy \param_strategy{area}
+
+\qbk{distinguish,with strategy}
+
+\qbk{[include reference/algorithms/correct.qbk]}
+*/
+template <typename Geometry, typename Strategy>
+inline void correct(Geometry& geometry, Strategy const& strategy)
+{
+ resolve_variant::correct<Geometry>::apply(geometry, strategy);
}
#if defined(_MSC_VER)
diff --git a/boost/geometry/algorithms/covered_by.hpp b/boost/geometry/algorithms/covered_by.hpp
index f9d9dcc486..d68429673a 100644
--- a/boost/geometry/algorithms/covered_by.hpp
+++ b/boost/geometry/algorithms/covered_by.hpp
@@ -20,443 +20,8 @@
#define BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP
-#include <cstddef>
+#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
-#include <boost/geometry/algorithms/not_implemented.hpp>
-#include <boost/geometry/algorithms/within.hpp>
-
-#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
-#include <boost/geometry/strategies/cartesian/box_in_box.hpp>
-#include <boost/geometry/strategies/default_strategy.hpp>
-
-namespace boost { namespace geometry
-{
-
-#ifndef DOXYGEN_NO_DETAIL
-namespace detail { namespace covered_by {
-
-struct use_point_in_geometry
-{
- template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
- {
- return detail::within::point_in_geometry(geometry1, geometry2, strategy) >= 0;
- }
-};
-
-struct use_relate
-{
- template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
- {
- typedef typename detail::de9im::static_mask_covered_by_type
- <
- Geometry1, Geometry2
- >::type covered_by_mask;
- return geometry::relate(geometry1, geometry2, covered_by_mask(), strategy);
- }
-};
-
-}} // namespace detail::covered_by
-#endif // DOXYGEN_NO_DETAIL
-
-#ifndef DOXYGEN_NO_DISPATCH
-namespace dispatch
-{
-
-template
-<
- typename Geometry1,
- typename Geometry2,
- typename Tag1 = typename tag<Geometry1>::type,
- typename Tag2 = typename tag<Geometry2>::type
->
-struct covered_by
- : not_implemented<Tag1, Tag2>
-{};
-
-
-template <typename Point, typename Box>
-struct covered_by<Point, Box, point_tag, box_tag>
-{
- template <typename Strategy>
- static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
- {
- ::boost::ignore_unused_variable_warning(strategy);
- return strategy.apply(point, box);
- }
-};
-
-template <typename Box1, typename Box2>
-struct covered_by<Box1, Box2, box_tag, box_tag>
-{
- template <typename Strategy>
- static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
- {
- assert_dimension_equal<Box1, Box2>();
- ::boost::ignore_unused_variable_warning(strategy);
- return strategy.apply(box1, box2);
- }
-};
-
-
-// P/P
-
-template <typename Point1, typename Point2>
-struct covered_by<Point1, Point2, point_tag, point_tag>
- : public detail::covered_by::use_point_in_geometry
-{};
-
-template <typename Point, typename MultiPoint>
-struct covered_by<Point, MultiPoint, point_tag, multi_point_tag>
- : public detail::covered_by::use_point_in_geometry
-{};
-
-// P/L
-
-template <typename Point, typename Segment>
-struct covered_by<Point, Segment, point_tag, segment_tag>
- : public detail::covered_by::use_point_in_geometry
-{};
-
-template <typename Point, typename Linestring>
-struct covered_by<Point, Linestring, point_tag, linestring_tag>
- : public detail::covered_by::use_point_in_geometry
-{};
-
-template <typename Point, typename MultiLinestring>
-struct covered_by<Point, MultiLinestring, point_tag, multi_linestring_tag>
- : public detail::covered_by::use_point_in_geometry
-{};
-
-// P/A
-
-template <typename Point, typename Ring>
-struct covered_by<Point, Ring, point_tag, ring_tag>
- : public detail::covered_by::use_point_in_geometry
-{};
-
-template <typename Point, typename Polygon>
-struct covered_by<Point, Polygon, point_tag, polygon_tag>
- : public detail::covered_by::use_point_in_geometry
-{};
-
-template <typename Point, typename MultiPolygon>
-struct covered_by<Point, MultiPolygon, point_tag, multi_polygon_tag>
- : public detail::covered_by::use_point_in_geometry
-{};
-
-// L/L
-
-template <typename Linestring1, typename Linestring2>
-struct covered_by<Linestring1, Linestring2, linestring_tag, linestring_tag>
- : public detail::covered_by::use_relate
-{};
-
-template <typename Linestring, typename MultiLinestring>
-struct covered_by<Linestring, MultiLinestring, linestring_tag, multi_linestring_tag>
- : public detail::covered_by::use_relate
-{};
-
-template <typename MultiLinestring, typename Linestring>
-struct covered_by<MultiLinestring, Linestring, multi_linestring_tag, linestring_tag>
- : public detail::covered_by::use_relate
-{};
-
-template <typename MultiLinestring1, typename MultiLinestring2>
-struct covered_by<MultiLinestring1, MultiLinestring2, multi_linestring_tag, multi_linestring_tag>
- : public detail::covered_by::use_relate
-{};
-
-// L/A
-
-template <typename Linestring, typename Ring>
-struct covered_by<Linestring, Ring, linestring_tag, ring_tag>
- : public detail::covered_by::use_relate
-{};
-
-template <typename MultiLinestring, typename Ring>
-struct covered_by<MultiLinestring, Ring, multi_linestring_tag, ring_tag>
- : public detail::covered_by::use_relate
-{};
-
-template <typename Linestring, typename Polygon>
-struct covered_by<Linestring, Polygon, linestring_tag, polygon_tag>
- : public detail::covered_by::use_relate
-{};
-
-template <typename MultiLinestring, typename Polygon>
-struct covered_by<MultiLinestring, Polygon, multi_linestring_tag, polygon_tag>
- : public detail::covered_by::use_relate
-{};
-
-template <typename Linestring, typename MultiPolygon>
-struct covered_by<Linestring, MultiPolygon, linestring_tag, multi_polygon_tag>
- : public detail::covered_by::use_relate
-{};
-
-template <typename MultiLinestring, typename MultiPolygon>
-struct covered_by<MultiLinestring, MultiPolygon, multi_linestring_tag, multi_polygon_tag>
- : public detail::covered_by::use_relate
-{};
-
-// A/A
-
-template <typename Ring1, typename Ring2>
-struct covered_by<Ring1, Ring2, ring_tag, ring_tag>
- : public detail::covered_by::use_relate
-{};
-
-template <typename Ring, typename Polygon>
-struct covered_by<Ring, Polygon, ring_tag, polygon_tag>
- : public detail::covered_by::use_relate
-{};
-
-template <typename Polygon, typename Ring>
-struct covered_by<Polygon, Ring, polygon_tag, ring_tag>
- : public detail::covered_by::use_relate
-{};
-
-template <typename Polygon1, typename Polygon2>
-struct covered_by<Polygon1, Polygon2, polygon_tag, polygon_tag>
- : public detail::covered_by::use_relate
-{};
-
-template <typename Ring, typename MultiPolygon>
-struct covered_by<Ring, MultiPolygon, ring_tag, multi_polygon_tag>
- : public detail::covered_by::use_relate
-{};
-
-template <typename MultiPolygon, typename Ring>
-struct covered_by<MultiPolygon, Ring, multi_polygon_tag, ring_tag>
- : public detail::covered_by::use_relate
-{};
-
-template <typename Polygon, typename MultiPolygon>
-struct covered_by<Polygon, MultiPolygon, polygon_tag, multi_polygon_tag>
- : public detail::covered_by::use_relate
-{};
-
-template <typename MultiPolygon, typename Polygon>
-struct covered_by<MultiPolygon, Polygon, multi_polygon_tag, polygon_tag>
- : public detail::covered_by::use_relate
-{};
-
-template <typename MultiPolygon1, typename MultiPolygon2>
-struct covered_by<MultiPolygon1, MultiPolygon2, multi_polygon_tag, multi_polygon_tag>
- : public detail::covered_by::use_relate
-{};
-
-} // namespace dispatch
-#endif // DOXYGEN_NO_DISPATCH
-
-
-namespace resolve_strategy {
-
-struct covered_by
-{
- template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- concepts::within::check
- <
- typename tag<Geometry1>::type,
- typename tag<Geometry2>::type,
- typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
- Strategy
- >();
- concepts::check<Geometry1 const>();
- concepts::check<Geometry2 const>();
- assert_dimension_equal<Geometry1, Geometry2>();
-
- return dispatch::covered_by<Geometry1, Geometry2>::apply(geometry1,
- geometry2,
- strategy);
- }
-
- template <typename Geometry1, typename Geometry2>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- default_strategy)
- {
- typedef typename strategy::covered_by::services::default_strategy
- <
- Geometry1,
- Geometry2
- >::type strategy_type;
-
- return covered_by::apply(geometry1, geometry2, strategy_type());
- }
-};
-
-} // namespace resolve_strategy
-
-
-namespace resolve_variant {
-
-template <typename Geometry1, typename Geometry2>
-struct covered_by
-{
- template <typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- return resolve_strategy::covered_by
- ::apply(geometry1, geometry2, strategy);
- }
-};
-
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct covered_by<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
-{
- template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
- {
- Geometry2 const& m_geometry2;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2, Strategy const& strategy)
- : m_geometry2(geometry2), m_strategy(strategy) {}
-
- template <typename Geometry1>
- bool operator()(Geometry1 const& geometry1) const
- {
- return covered_by<Geometry1, Geometry2>
- ::apply(geometry1, m_geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
- }
-};
-
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct covered_by<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
-{
- template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
- {
- Geometry1 const& m_geometry1;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1, Strategy const& strategy)
- : m_geometry1(geometry1), m_strategy(strategy) {}
-
- template <typename Geometry2>
- bool operator()(Geometry2 const& geometry2) const
- {
- return covered_by<Geometry1, Geometry2>
- ::apply(m_geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool
- apply(Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
- }
-};
-
-template <
- BOOST_VARIANT_ENUM_PARAMS(typename T1),
- BOOST_VARIANT_ENUM_PARAMS(typename T2)
->
-struct covered_by<
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
->
-{
- template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
- {
- Strategy const& m_strategy;
-
- visitor(Strategy const& strategy): m_strategy(strategy) {}
-
- template <typename Geometry1, typename Geometry2>
- bool operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
- {
- return covered_by<Geometry1, Geometry2>
- ::apply(geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
- }
-};
-
-} // namespace resolve_variant
-
-
-/*!
-\brief \brief_check12{is inside or on border}
-\ingroup covered_by
-\details \details_check12{covered_by, is inside or on border}.
-\tparam Geometry1 \tparam_geometry
-\tparam Geometry2 \tparam_geometry
-\param geometry1 \param_geometry which might be inside or on the border of the second geometry
-\param geometry2 \param_geometry which might cover the first geometry
-\return true if geometry1 is inside of or on the border of geometry2,
- else false
-\note The default strategy is used for covered_by detection
-
-\qbk{[include reference/algorithms/covered_by.qbk]}
-
- */
-template<typename Geometry1, typename Geometry2>
-inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2)
-{
- return resolve_variant::covered_by<Geometry1, Geometry2>
- ::apply(geometry1, geometry2, default_strategy());
-}
-
-/*!
-\brief \brief_check12{is inside or on border} \brief_strategy
-\ingroup covered_by
-\details \details_check12{covered_by, is inside or on border}, \brief_strategy. \details_strategy_reasons
-\tparam Geometry1 \tparam_geometry
-\tparam Geometry2 \tparam_geometry
-\param geometry1 \param_geometry which might be inside or on the border of the second geometry
-\param geometry2 \param_geometry which might cover the first geometry
-\param strategy strategy to be used
-\return true if geometry1 is inside of or on the border of geometry2,
- else false
-
-\qbk{distinguish,with strategy}
-\qbk{[include reference/algorithms/covered_by.qbk]}
-
-*/
-template<typename Geometry1, typename Geometry2, typename Strategy>
-inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2,
- Strategy const& strategy)
-{
- return resolve_variant::covered_by<Geometry1, Geometry2>
- ::apply(geometry1, geometry2, strategy);
-}
-
-}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP
diff --git a/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
index 029053dda3..a149f1dd46 100644
--- a/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
@@ -122,7 +122,8 @@ struct buffer_range
typename DistanceStrategy,
typename JoinStrategy,
typename EndStrategy,
- typename RobustPolicy
+ typename RobustPolicy,
+ typename Strategy
>
static inline
void add_join(Collection& collection,
@@ -133,18 +134,19 @@ struct buffer_range
Point const& input,
output_point_type const& perp1,
output_point_type const& perp2,
- strategy::buffer::buffer_side_selector side,
+ geometry::strategy::buffer::buffer_side_selector side,
DistanceStrategy const& distance,
JoinStrategy const& join_strategy,
EndStrategy const& end_strategy,
- RobustPolicy const& )
+ RobustPolicy const& ,
+ Strategy const& strategy) // side strategy
{
output_point_type intersection_point;
geometry::assign_zero(intersection_point);
- strategy::buffer::join_selector join
- = get_join_type(penultimate_input, previous_input, input);
- if (join == strategy::buffer::join_convex)
+ geometry::strategy::buffer::join_selector join
+ = get_join_type(penultimate_input, previous_input, input, strategy);
+ if (join == geometry::strategy::buffer::join_convex)
{
// Calculate the intersection-point formed by the two sides.
// It might be that the two sides are not convex, but continue
@@ -157,23 +159,23 @@ struct buffer_range
switch(join)
{
- case strategy::buffer::join_continue :
+ case geometry::strategy::buffer::join_continue :
// No join, we get two consecutive sides
break;
- case strategy::buffer::join_concave :
+ case geometry::strategy::buffer::join_concave :
{
std::vector<output_point_type> range_out;
range_out.push_back(prev_perp2);
range_out.push_back(previous_input);
- collection.add_piece(strategy::buffer::buffered_concave, previous_input, range_out);
+ collection.add_piece(geometry::strategy::buffer::buffered_concave, previous_input, range_out);
range_out.clear();
range_out.push_back(previous_input);
range_out.push_back(perp1);
- collection.add_piece(strategy::buffer::buffered_concave, previous_input, range_out);
+ collection.add_piece(geometry::strategy::buffer::buffered_concave, previous_input, range_out);
}
break;
- case strategy::buffer::join_spike :
+ case geometry::strategy::buffer::join_spike :
{
// For linestrings, only add spike at one side to avoid
// duplicates
@@ -183,7 +185,7 @@ struct buffer_range
collection.set_current_ring_concave();
}
break;
- case strategy::buffer::join_convex :
+ case geometry::strategy::buffer::join_convex :
{
// The corner is convex, we create a join
// TODO (future) - avoid a separate vector, add the piece directly
@@ -193,7 +195,7 @@ struct buffer_range
distance.apply(previous_input, input, side),
range_out))
{
- collection.add_piece(strategy::buffer::buffered_join,
+ collection.add_piece(geometry::strategy::buffer::buffered_join,
previous_input, range_out);
}
}
@@ -201,27 +203,24 @@ struct buffer_range
}
}
- static inline strategy::buffer::join_selector get_join_type(
+ template <typename Strategy>
+ static inline geometry::strategy::buffer::join_selector get_join_type(
output_point_type const& p0,
output_point_type const& p1,
- output_point_type const& p2)
+ output_point_type const& p2,
+ Strategy const& strategy) // side strategy
{
- typedef typename strategy::side::services::default_strategy
- <
- typename cs_tag<output_point_type>::type
- >::type side_strategy;
-
- int const side = side_strategy::apply(p0, p1, p2);
- return side == -1 ? strategy::buffer::join_convex
- : side == 1 ? strategy::buffer::join_concave
+ int const side = strategy.apply(p0, p1, p2);
+ return side == -1 ? geometry::strategy::buffer::join_convex
+ : side == 1 ? geometry::strategy::buffer::join_concave
: parallel_continue
(
get<0>(p2) - get<0>(p1),
get<1>(p2) - get<1>(p1),
get<0>(p1) - get<0>(p0),
get<1>(p1) - get<1>(p0)
- ) ? strategy::buffer::join_continue
- : strategy::buffer::join_spike;
+ ) ? geometry::strategy::buffer::join_continue
+ : geometry::strategy::buffer::join_spike;
}
template
@@ -232,16 +231,18 @@ struct buffer_range
typename SideStrategy,
typename JoinStrategy,
typename EndStrategy,
- typename RobustPolicy
+ typename RobustPolicy,
+ typename Strategy
>
- static inline strategy::buffer::result_code iterate(Collection& collection,
+ static inline geometry::strategy::buffer::result_code iterate(Collection& collection,
Iterator begin, Iterator end,
- strategy::buffer::buffer_side_selector side,
+ geometry::strategy::buffer::buffer_side_selector side,
DistanceStrategy const& distance_strategy,
SideStrategy const& side_strategy,
JoinStrategy const& join_strategy,
EndStrategy const& end_strategy,
RobustPolicy const& robust_policy,
+ Strategy const& strategy, // side strategy
output_point_type& first_p1,
output_point_type& first_p2,
output_point_type& last_p1,
@@ -273,7 +274,7 @@ struct buffer_range
* pup: penultimate_point
*/
- strategy::buffer::result_code result = strategy::buffer::result_no_output;
+ geometry::strategy::buffer::result_code result = geometry::strategy::buffer::result_no_output;
bool first = true;
Iterator it = begin;
@@ -284,25 +285,25 @@ struct buffer_range
for (Iterator prev = it++; it != end; ++it)
{
generated_side.clear();
- strategy::buffer::result_code error_code
+ geometry::strategy::buffer::result_code error_code
= side_strategy.apply(*prev, *it, side,
distance_strategy, generated_side);
- if (error_code == strategy::buffer::result_no_output)
+ if (error_code == geometry::strategy::buffer::result_no_output)
{
// Because input is simplified, this is improbable,
// but it can happen for degenerate geometries
// Further handling of this side is skipped
continue;
}
- else if (error_code == strategy::buffer::result_error_numerical)
+ else if (error_code == geometry::strategy::buffer::result_error_numerical)
{
return error_code;
}
BOOST_GEOMETRY_ASSERT(! generated_side.empty());
- result = strategy::buffer::result_normal;
+ result = geometry::strategy::buffer::result_normal;
if (! first)
{
@@ -312,7 +313,7 @@ struct buffer_range
*it, generated_side.front(), generated_side.back(),
side,
distance_strategy, join_strategy, end_strategy,
- robust_policy);
+ robust_policy, strategy);
}
collection.add_side_piece(*prev, *it, generated_side, first);
@@ -350,7 +351,8 @@ struct buffer_multi
typename JoinStrategy,
typename EndStrategy,
typename PointStrategy,
- typename RobustPolicy
+ typename RobustPolicy,
+ typename Strategy
>
static inline void apply(Multi const& multi,
Collection& collection,
@@ -359,7 +361,8 @@ struct buffer_multi
JoinStrategy const& join_strategy,
EndStrategy const& end_strategy,
PointStrategy const& point_strategy,
- RobustPolicy const& robust_policy)
+ RobustPolicy const& robust_policy,
+ Strategy const& strategy) // side strategy
{
for (typename boost::range_iterator<Multi const>::type
it = boost::begin(multi);
@@ -369,7 +372,7 @@ struct buffer_multi
Policy::apply(*it, collection,
distance_strategy, side_strategy,
join_strategy, end_strategy, point_strategy,
- robust_policy);
+ robust_policy, strategy);
}
}
};
@@ -396,9 +399,9 @@ inline void buffer_point(Point const& point, Collection& collection,
collection.start_new_ring();
std::vector<OutputPointType> range_out;
point_strategy.apply(point, distance_strategy, range_out);
- collection.add_piece(strategy::buffer::buffered_point, range_out, false);
+ collection.add_piece(geometry::strategy::buffer::buffered_point, range_out, false);
collection.set_piece_center(point);
- collection.finish_ring(strategy::buffer::result_normal);
+ collection.finish_ring(geometry::strategy::buffer::result_normal);
}
@@ -436,7 +439,8 @@ struct buffer_inserter<point_tag, Point, RingOutput>
typename JoinStrategy,
typename EndStrategy,
typename PointStrategy,
- typename RobustPolicy
+ typename RobustPolicy,
+ typename Strategy
>
static inline void apply(Point const& point, Collection& collection,
DistanceStrategy const& distance_strategy,
@@ -444,7 +448,8 @@ struct buffer_inserter<point_tag, Point, RingOutput>
JoinStrategy const& ,
EndStrategy const& ,
PointStrategy const& point_strategy,
- RobustPolicy const& )
+ RobustPolicy const& ,
+ Strategy const& ) // side strategy
{
detail::buffer::buffer_point
<
@@ -472,29 +477,32 @@ struct buffer_inserter_ring
typename SideStrategy,
typename JoinStrategy,
typename EndStrategy,
- typename RobustPolicy
+ typename RobustPolicy,
+ typename Strategy
>
- static inline strategy::buffer::result_code iterate(Collection& collection,
+ static inline geometry::strategy::buffer::result_code iterate(Collection& collection,
Iterator begin, Iterator end,
- strategy::buffer::buffer_side_selector side,
+ geometry::strategy::buffer::buffer_side_selector side,
DistanceStrategy const& distance_strategy,
SideStrategy const& side_strategy,
JoinStrategy const& join_strategy,
EndStrategy const& end_strategy,
- RobustPolicy const& robust_policy)
+ RobustPolicy const& robust_policy,
+ Strategy const& strategy) // side strategy
{
output_point_type first_p1, first_p2, last_p1, last_p2;
typedef detail::buffer::buffer_range<RingOutput> buffer_range;
- strategy::buffer::result_code result
+ geometry::strategy::buffer::result_code result
= buffer_range::iterate(collection, begin, end,
side,
- distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy,
+ distance_strategy, side_strategy, join_strategy, end_strategy,
+ robust_policy, strategy,
first_p1, first_p2, last_p1, last_p2);
// Generate closing join
- if (result == strategy::buffer::result_normal)
+ if (result == geometry::strategy::buffer::result_normal)
{
buffer_range::add_join(collection,
*(end - 2),
@@ -502,7 +510,7 @@ struct buffer_inserter_ring
*(begin + 1), first_p1, first_p2,
side,
distance_strategy, join_strategy, end_strategy,
- robust_policy);
+ robust_policy, strategy);
}
// Buffer is closed automatically by last closing corner
@@ -517,21 +525,23 @@ struct buffer_inserter_ring
typename JoinStrategy,
typename EndStrategy,
typename PointStrategy,
- typename RobustPolicy
+ typename RobustPolicy,
+ typename Strategy
>
- static inline strategy::buffer::result_code apply(RingInput const& ring,
+ static inline geometry::strategy::buffer::result_code apply(RingInput const& ring,
Collection& collection,
DistanceStrategy const& distance,
SideStrategy const& side_strategy,
JoinStrategy const& join_strategy,
EndStrategy const& end_strategy,
PointStrategy const& point_strategy,
- RobustPolicy const& robust_policy)
+ RobustPolicy const& robust_policy,
+ Strategy const& strategy) // side strategy
{
RingInput simplified;
detail::buffer::simplify_input(ring, distance, simplified);
- strategy::buffer::result_code code = strategy::buffer::result_no_output;
+ geometry::strategy::buffer::result_code code = geometry::strategy::buffer::result_no_output;
std::size_t n = boost::size(simplified);
std::size_t const min_points = core_detail::closure::minimum_ring_size
@@ -546,18 +556,20 @@ struct buffer_inserter_ring
{
// Walk backwards (rings will be reversed afterwards)
code = iterate(collection, boost::rbegin(view), boost::rend(view),
- strategy::buffer::buffer_side_right,
- distance, side_strategy, join_strategy, end_strategy, robust_policy);
+ geometry::strategy::buffer::buffer_side_right,
+ distance, side_strategy, join_strategy, end_strategy,
+ robust_policy, strategy);
}
else
{
code = iterate(collection, boost::begin(view), boost::end(view),
- strategy::buffer::buffer_side_left,
- distance, side_strategy, join_strategy, end_strategy, robust_policy);
+ geometry::strategy::buffer::buffer_side_left,
+ distance, side_strategy, join_strategy, end_strategy,
+ robust_policy, strategy);
}
}
- if (code == strategy::buffer::result_no_output && n >= 1)
+ if (code == geometry::strategy::buffer::result_no_output && n >= 1)
{
// Use point_strategy to buffer degenerated ring
detail::buffer::buffer_point<output_point_type>
@@ -586,23 +598,25 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput>
typename JoinStrategy,
typename EndStrategy,
typename PointStrategy,
- typename RobustPolicy
+ typename RobustPolicy,
+ typename Strategy
>
- static inline strategy::buffer::result_code apply(RingInput const& ring,
+ static inline geometry::strategy::buffer::result_code apply(RingInput const& ring,
Collection& collection,
DistanceStrategy const& distance,
SideStrategy const& side_strategy,
JoinStrategy const& join_strategy,
EndStrategy const& end_strategy,
PointStrategy const& point_strategy,
- RobustPolicy const& robust_policy)
+ RobustPolicy const& robust_policy,
+ Strategy const& strategy) // side strategy
{
collection.start_new_ring();
- strategy::buffer::result_code const code
+ geometry::strategy::buffer::result_code const code
= buffer_inserter_ring<RingInput, RingOutput>::apply(ring,
collection, distance,
side_strategy, join_strategy, end_strategy, point_strategy,
- robust_policy);
+ robust_policy, strategy);
collection.finish_ring(code);
return code;
}
@@ -627,16 +641,18 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
typename SideStrategy,
typename JoinStrategy,
typename EndStrategy,
- typename RobustPolicy
+ typename RobustPolicy,
+ typename Strategy
>
- static inline strategy::buffer::result_code iterate(Collection& collection,
+ static inline geometry::strategy::buffer::result_code iterate(Collection& collection,
Iterator begin, Iterator end,
- strategy::buffer::buffer_side_selector side,
+ geometry::strategy::buffer::buffer_side_selector side,
DistanceStrategy const& distance_strategy,
SideStrategy const& side_strategy,
JoinStrategy const& join_strategy,
EndStrategy const& end_strategy,
RobustPolicy const& robust_policy,
+ Strategy const& strategy, // side strategy
output_point_type& first_p1)
{
input_point_type const& ultimate_point = *(end - 1);
@@ -647,18 +663,18 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
// we have it already from the first phase (left).
// But for the first pass, we have to generate it
output_point_type reverse_p1;
- if (side == strategy::buffer::buffer_side_right)
+ if (side == geometry::strategy::buffer::buffer_side_right)
{
reverse_p1 = first_p1;
}
else
{
std::vector<output_point_type> generated_side;
- strategy::buffer::result_code code
+ geometry::strategy::buffer::result_code code
= side_strategy.apply(ultimate_point, penultimate_point,
- strategy::buffer::buffer_side_right,
+ geometry::strategy::buffer::buffer_side_right,
distance_strategy, generated_side);
- if (code != strategy::buffer::result_normal)
+ if (code != geometry::strategy::buffer::result_normal)
{
// No output or numerical error
return code;
@@ -668,16 +684,18 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
output_point_type first_p2, last_p1, last_p2;
- strategy::buffer::result_code result
+ geometry::strategy::buffer::result_code result
= detail::buffer::buffer_range<output_ring_type>::iterate(collection,
begin, end, side,
- distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy,
+ distance_strategy, side_strategy, join_strategy, end_strategy,
+ robust_policy, strategy,
first_p1, first_p2, last_p1, last_p2);
- if (result == strategy::buffer::result_normal)
+ if (result == geometry::strategy::buffer::result_normal)
{
std::vector<output_point_type> range_out;
- end_strategy.apply(penultimate_point, last_p2, ultimate_point, reverse_p1, side, distance_strategy, range_out);
+ end_strategy.apply(penultimate_point, last_p2, ultimate_point, reverse_p1,
+ side, distance_strategy, range_out);
collection.add_endcap(end_strategy, range_out, ultimate_point);
}
return result;
@@ -691,20 +709,23 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
typename JoinStrategy,
typename EndStrategy,
typename PointStrategy,
- typename RobustPolicy
+ typename RobustPolicy,
+ typename Strategy
>
- static inline strategy::buffer::result_code apply(Linestring const& linestring, Collection& collection,
+ static inline geometry::strategy::buffer::result_code apply(Linestring const& linestring,
+ Collection& collection,
DistanceStrategy const& distance,
SideStrategy const& side_strategy,
JoinStrategy const& join_strategy,
EndStrategy const& end_strategy,
PointStrategy const& point_strategy,
- RobustPolicy const& robust_policy)
+ RobustPolicy const& robust_policy,
+ Strategy const& strategy) // side strategy
{
Linestring simplified;
detail::buffer::simplify_input(linestring, distance, simplified);
- strategy::buffer::result_code code = strategy::buffer::result_no_output;
+ geometry::strategy::buffer::result_code code = geometry::strategy::buffer::result_no_output;
std::size_t n = boost::size(simplified);
if (n > 1)
{
@@ -712,21 +733,23 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
output_point_type first_p1;
code = iterate(collection,
boost::begin(simplified), boost::end(simplified),
- strategy::buffer::buffer_side_left,
- distance, side_strategy, join_strategy, end_strategy, robust_policy,
+ geometry::strategy::buffer::buffer_side_left,
+ distance, side_strategy, join_strategy, end_strategy,
+ robust_policy, strategy,
first_p1);
- if (code == strategy::buffer::result_normal)
+ if (code == geometry::strategy::buffer::result_normal)
{
code = iterate(collection,
boost::rbegin(simplified), boost::rend(simplified),
- strategy::buffer::buffer_side_right,
- distance, side_strategy, join_strategy, end_strategy, robust_policy,
+ geometry::strategy::buffer::buffer_side_right,
+ distance, side_strategy, join_strategy, end_strategy,
+ robust_policy, strategy,
first_p1);
}
collection.finish_ring(code);
}
- if (code == strategy::buffer::result_no_output && n >= 1)
+ if (code == geometry::strategy::buffer::result_no_output && n >= 1)
{
// Use point_strategy to buffer degenerated linestring
detail::buffer::buffer_point<output_point_type>
@@ -763,7 +786,8 @@ private:
typename JoinStrategy,
typename EndStrategy,
typename PointStrategy,
- typename RobustPolicy
+ typename RobustPolicy,
+ typename Strategy
>
static inline
void iterate(Iterator begin, Iterator end,
@@ -774,15 +798,16 @@ private:
EndStrategy const& end_strategy,
PointStrategy const& point_strategy,
RobustPolicy const& robust_policy,
+ Strategy const& strategy, // side strategy
bool is_interior)
{
for (Iterator it = begin; it != end; ++it)
{
collection.start_new_ring();
- strategy::buffer::result_code const code
+ geometry::strategy::buffer::result_code const code
= policy::apply(*it, collection, distance, side_strategy,
join_strategy, end_strategy, point_strategy,
- robust_policy);
+ robust_policy, strategy);
collection.finish_ring(code, is_interior);
}
@@ -797,7 +822,8 @@ private:
typename JoinStrategy,
typename EndStrategy,
typename PointStrategy,
- typename RobustPolicy
+ typename RobustPolicy,
+ typename Strategy
>
static inline
void apply_interior_rings(InteriorRings const& interior_rings,
@@ -807,12 +833,13 @@ private:
JoinStrategy const& join_strategy,
EndStrategy const& end_strategy,
PointStrategy const& point_strategy,
- RobustPolicy const& robust_policy)
+ RobustPolicy const& robust_policy,
+ Strategy const& strategy) // side strategy
{
iterate(boost::begin(interior_rings), boost::end(interior_rings),
collection, distance, side_strategy,
join_strategy, end_strategy, point_strategy,
- robust_policy, true);
+ robust_policy, strategy, true);
}
public:
@@ -824,7 +851,8 @@ public:
typename JoinStrategy,
typename EndStrategy,
typename PointStrategy,
- typename RobustPolicy
+ typename RobustPolicy,
+ typename Strategy
>
static inline void apply(PolygonInput const& polygon,
Collection& collection,
@@ -833,16 +861,17 @@ public:
JoinStrategy const& join_strategy,
EndStrategy const& end_strategy,
PointStrategy const& point_strategy,
- RobustPolicy const& robust_policy)
+ RobustPolicy const& robust_policy,
+ Strategy const& strategy) // side strategy
{
{
collection.start_new_ring();
- strategy::buffer::result_code const code
+ geometry::strategy::buffer::result_code const code
= policy::apply(exterior_ring(polygon), collection,
distance, side_strategy,
join_strategy, end_strategy, point_strategy,
- robust_policy);
+ robust_policy, strategy);
collection.finish_ring(code, false,
geometry::num_interior_rings(polygon) > 0u);
@@ -851,7 +880,7 @@ public:
apply_interior_rings(interior_rings(polygon),
collection, distance, side_strategy,
join_strategy, end_strategy, point_strategy,
- robust_policy);
+ robust_policy, strategy);
}
};
@@ -945,7 +974,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
>::apply(geometry_input, collection,
distance_strategy, side_strategy, join_strategy,
end_strategy, point_strategy,
- robust_policy);
+ robust_policy, intersection_strategy.get_side_strategy());
collection.get_turns();
collection.classify_turns(linear);
diff --git a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
index 7fbbb790bb..c0d906fe62 100644
--- a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
@@ -142,10 +142,20 @@ struct buffered_piece_collection
robust_point_type
>::type robust_comparable_radius_type;
- typedef typename strategy::side::services::default_strategy
+ typedef typename IntersectionStrategy::side_strategy_type side_strategy_type;
+
+ typedef typename IntersectionStrategy::template area_strategy
+ <
+ point_type
+ >::type area_strategy_type;
+
+ typedef typename IntersectionStrategy::template area_strategy
<
- typename cs_tag<point_type>::type
- >::type side_strategy;
+ robust_point_type
+ >::type robust_area_strategy_type;
+
+ typedef typename area_strategy_type::return_type area_result_type;
+ typedef typename robust_area_strategy_type::return_type robust_area_result_type;
typedef typename geometry::rescale_policy_type
<
@@ -306,7 +316,10 @@ struct buffered_piece_collection
cluster_type m_clusters;
- IntersectionStrategy const& m_intersection_strategy;
+ IntersectionStrategy m_intersection_strategy;
+ side_strategy_type m_side_strategy;
+ area_strategy_type m_area_strategy;
+ robust_area_strategy_type m_robust_area_strategy;
RobustPolicy const& m_robust_policy;
struct redundant_turn
@@ -321,6 +334,9 @@ struct buffered_piece_collection
RobustPolicy const& robust_policy)
: m_first_piece_index(-1)
, m_intersection_strategy(intersection_strategy)
+ , m_side_strategy(intersection_strategy.get_side_strategy())
+ , m_area_strategy(intersection_strategy.template get_area_strategy<point_type>())
+ , m_robust_area_strategy(intersection_strategy.template get_area_strategy<robust_point_type>())
, m_robust_policy(robust_policy)
{}
@@ -478,7 +494,7 @@ struct buffered_piece_collection
for (typename occupation_map_type::iterator it = occupation_map.begin();
it != occupation_map.end(); ++it)
{
- it->second.get_left_turns(it->first, m_turns);
+ it->second.get_left_turns(it->first, m_turns, m_side_strategy);
}
}
@@ -699,7 +715,7 @@ struct buffered_piece_collection
++it)
{
piece& pc = *it;
- if (geometry::area(pc.robust_ring) < 0)
+ if (geometry::area(pc.robust_ring, m_robust_area_strategy) < 0)
{
// Rings can be ccw:
// - in a concave piece
@@ -1220,14 +1236,9 @@ struct buffered_piece_collection
inline void enrich()
{
- typedef typename strategy::side::services::default_strategy
- <
- typename cs_tag<Ring>::type
- >::type side_strategy_type;
-
enrich_intersection_points<false, false, overlay_buffer>(m_turns,
m_clusters, offsetted_rings, offsetted_rings,
- m_robust_policy, side_strategy_type());
+ m_robust_policy, m_side_strategy);
}
// Discards all rings which do have not-OK intersection points only.
@@ -1314,7 +1325,7 @@ struct buffered_piece_collection
buffered_ring<Ring>& ring = *it;
if (! ring.has_intersections()
&& boost::size(ring) > 0u
- && geometry::area(ring) < 0)
+ && geometry::area(ring, m_area_strategy) < 0)
{
if (! point_coveredby_original(geometry::range::front(ring)))
{
@@ -1391,7 +1402,7 @@ struct buffered_piece_collection
template <typename GeometryOutput, typename OutputIterator>
inline OutputIterator assign(OutputIterator out) const
{
- typedef detail::overlay::ring_properties<point_type> properties;
+ typedef detail::overlay::ring_properties<point_type, area_result_type> properties;
std::map<ring_identifier, properties> selected;
@@ -1407,7 +1418,7 @@ struct buffered_piece_collection
if (! it->has_intersections()
&& ! it->is_untouched_outside_original)
{
- properties p = properties(*it);
+ properties p = properties(*it, m_area_strategy);
if (p.valid)
{
ring_identifier id(0, index, -1);
@@ -1423,7 +1434,7 @@ struct buffered_piece_collection
it != boost::end(traversed_rings);
++it, ++index)
{
- properties p = properties(*it);
+ properties p = properties(*it, m_area_strategy);
if (p.valid)
{
ring_identifier id(2, index, -1);
@@ -1431,7 +1442,7 @@ struct buffered_piece_collection
}
}
- detail::overlay::assign_parents(offsetted_rings, traversed_rings, selected, true);
+ detail::overlay::assign_parents(offsetted_rings, traversed_rings, selected, m_intersection_strategy, true);
return detail::overlay::add_rings<GeometryOutput>(selected, offsetted_rings, traversed_rings, out);
}
diff --git a/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp b/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
index 178c7bcafe..5c012e7151 100644
--- a/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
+++ b/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
@@ -126,26 +127,31 @@ class piece_turn_visitor
template <std::size_t Dimension, typename Iterator, typename Box>
inline void move_begin_iterator(Iterator& it_begin, Iterator it_beyond,
- signed_size_type& index, int dir, Box const& other_bounding_box)
+ signed_size_type& index, int dir,
+ Box const& this_bounding_box,
+ Box const& other_bounding_box)
{
for(; it_begin != it_beyond
&& it_begin + 1 != it_beyond
&& detail::section::preceding<Dimension>(dir, *(it_begin + 1),
- other_bounding_box, m_robust_policy);
+ this_bounding_box,
+ other_bounding_box,
+ m_robust_policy);
++it_begin, index++)
{}
}
template <std::size_t Dimension, typename Iterator, typename Box>
inline void move_end_iterator(Iterator it_begin, Iterator& it_beyond,
- int dir, Box const& other_bounding_box)
+ int dir, Box const& this_bounding_box,
+ Box const& other_bounding_box)
{
while (it_beyond != it_begin
&& it_beyond - 1 != it_begin
&& it_beyond - 2 != it_begin)
{
if (detail::section::exceeding<Dimension>(dir, *(it_beyond - 2),
- other_bounding_box, m_robust_policy))
+ this_bounding_box, other_bounding_box, m_robust_policy))
{
--it_beyond;
}
@@ -191,23 +197,23 @@ class piece_turn_visitor
// Set begin/end of monotonic ranges, in both x/y directions
signed_size_type index1 = sec1_first_index;
move_begin_iterator<0>(it1_first, it1_beyond, index1,
- section1.directions[0], section2.bounding_box);
+ section1.directions[0], section1.bounding_box, section2.bounding_box);
move_end_iterator<0>(it1_first, it1_beyond,
- section1.directions[0], section2.bounding_box);
+ section1.directions[0], section1.bounding_box, section2.bounding_box);
move_begin_iterator<1>(it1_first, it1_beyond, index1,
- section1.directions[1], section2.bounding_box);
+ section1.directions[1], section1.bounding_box, section2.bounding_box);
move_end_iterator<1>(it1_first, it1_beyond,
- section1.directions[1], section2.bounding_box);
+ section1.directions[1], section1.bounding_box, section2.bounding_box);
signed_size_type index2 = sec2_first_index;
move_begin_iterator<0>(it2_first, it2_beyond, index2,
- section2.directions[0], section1.bounding_box);
+ section2.directions[0], section2.bounding_box, section1.bounding_box);
move_end_iterator<0>(it2_first, it2_beyond,
- section2.directions[0], section1.bounding_box);
+ section2.directions[0], section2.bounding_box, section1.bounding_box);
move_begin_iterator<1>(it2_first, it2_beyond, index2,
- section2.directions[1], section1.bounding_box);
+ section2.directions[1], section2.bounding_box, section1.bounding_box);
move_end_iterator<1>(it2_first, it2_beyond,
- section2.directions[1], section1.bounding_box);
+ section2.directions[1], section2.bounding_box, section1.bounding_box);
turn_type the_model;
the_model.operations[0].piece_index = piece1.index;
@@ -272,7 +278,7 @@ public:
{}
template <typename Section>
- inline void apply(Section const& section1, Section const& section2,
+ inline bool apply(Section const& section1, Section const& section2,
bool first = true)
{
boost::ignore_unused_variable_warning(first);
@@ -285,12 +291,14 @@ public:
|| is_adjacent(piece1, piece2)
|| is_on_same_convex_ring(piece1, piece2)
|| detail::disjoint::disjoint_box_box(section1.bounding_box,
- section2.bounding_box) )
+ section2.bounding_box) )
{
- return;
+ return true;
}
calculate_turns(piece1, piece2, section1, section2);
+
+ return true;
}
};
diff --git a/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp b/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp
index da1d084d32..e7cc97539f 100644
--- a/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp
+++ b/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp
@@ -212,27 +212,27 @@ public:
{}
template <typename Turn, typename Original>
- inline void apply(Turn const& turn, Original const& original, bool first = true)
+ inline bool apply(Turn const& turn, Original const& original, bool first = true)
{
boost::ignore_unused_variable_warning(first);
if (turn.location != location_ok || turn.within_original)
{
// Skip all points already processed
- return;
+ return true;
}
if (geometry::disjoint(turn.robust_point, original.m_box))
{
// Skip all disjoint
- return;
+ return true;
}
int const code = point_in_original(turn.robust_point, original);
if (code == -1)
{
- return;
+ return true;
}
Turn& mutable_turn = m_mutable_turns[turn.turn_index];
@@ -259,6 +259,8 @@ public:
mutable_turn.within_original = true;
mutable_turn.count_in_original = 1;
}
+
+ return true;
}
private :
diff --git a/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp b/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp
index d7146befb9..d23a3b3fd6 100644
--- a/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp
+++ b/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2016.
// Modifications copyright (c) 2016 Oracle and/or its affiliates.
@@ -686,32 +687,32 @@ public:
{}
template <typename Turn, typename Piece>
- inline void apply(Turn const& turn, Piece const& piece, bool first = true)
+ inline bool apply(Turn const& turn, Piece const& piece, bool first = true)
{
boost::ignore_unused_variable_warning(first);
if (turn.count_within > 0)
{
// Already inside - no need to check again
- return;
+ return true;
}
if (piece.type == strategy::buffer::buffered_flat_end
|| piece.type == strategy::buffer::buffered_concave)
{
// Turns cannot be located within flat-end or concave pieces
- return;
+ return true;
}
if (! geometry::covered_by(turn.robust_point, piece.robust_envelope))
{
// Easy check: if the turn is not in the envelope, we can safely return
- return;
+ return true;
}
if (skip(turn.operations[0], piece) || skip(turn.operations[1], piece))
{
- return;
+ return true;
}
// TODO: mutable_piece to make some on-demand preparations in analyse
@@ -733,11 +734,11 @@ public:
if (cd < piece.robust_min_comparable_radius)
{
mutable_turn.count_within++;
- return;
+ return true;
}
if (cd > piece.robust_max_comparable_radius)
{
- return;
+ return true;
}
}
@@ -749,20 +750,20 @@ public:
switch(analyse_code)
{
case analyse_disjoint :
- return;
+ return true;
case analyse_on_offsetted :
mutable_turn.count_on_offsetted++; // value is not used anymore
- return;
+ return true;
case analyse_on_original_boundary :
mutable_turn.count_on_original_boundary++;
- return;
+ return true;
case analyse_within :
mutable_turn.count_within++;
- return;
+ return true;
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
case analyse_near_offsetted :
mutable_turn.count_within_near_offsetted++;
- return;
+ return true;
#endif
default :
break;
@@ -790,6 +791,8 @@ public:
{
mutable_turn.count_within++;
}
+
+ return true;
}
};
diff --git a/boost/geometry/algorithms/detail/covered_by/implementation.hpp b/boost/geometry/algorithms/detail/covered_by/implementation.hpp
new file mode 100644
index 0000000000..3df8b7783d
--- /dev/null
+++ b/boost/geometry/algorithms/detail/covered_by/implementation.hpp
@@ -0,0 +1,280 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// This file was modified by Oracle on 2013, 2014, 2017.
+// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the 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_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_IMPLEMENTATION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_IMPLEMENTATION_HPP
+
+
+#include <cstddef>
+
+#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
+#include <boost/geometry/algorithms/detail/within/implementation.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace covered_by {
+
+struct use_point_in_geometry
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
+ {
+ return detail::within::point_in_geometry(geometry1, geometry2, strategy) >= 0;
+ }
+};
+
+struct use_relate
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
+ {
+ typedef typename detail::de9im::static_mask_covered_by_type
+ <
+ Geometry1, Geometry2
+ >::type covered_by_mask;
+ return geometry::relate(geometry1, geometry2, covered_by_mask(), strategy);
+ }
+};
+
+}} // namespace detail::covered_by
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Point, typename Box>
+struct covered_by<Point, Box, point_tag, box_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
+ {
+ ::boost::ignore_unused_variable_warning(strategy);
+ return strategy.apply(point, box);
+ }
+};
+
+template <typename Box1, typename Box2>
+struct covered_by<Box1, Box2, box_tag, box_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
+ {
+ assert_dimension_equal<Box1, Box2>();
+ ::boost::ignore_unused_variable_warning(strategy);
+ return strategy.apply(box1, box2);
+ }
+};
+
+
+// P/P
+
+template <typename Point1, typename Point2>
+struct covered_by<Point1, Point2, point_tag, point_tag>
+ : public detail::covered_by::use_point_in_geometry
+{};
+
+template <typename Point, typename MultiPoint>
+struct covered_by<Point, MultiPoint, point_tag, multi_point_tag>
+ : public detail::covered_by::use_point_in_geometry
+{};
+
+template <typename MultiPoint, typename Point>
+struct covered_by<MultiPoint, Point, multi_point_tag, point_tag>
+ : public detail::within::multi_point_point
+{};
+
+template <typename MultiPoint1, typename MultiPoint2>
+struct covered_by<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag>
+ : public detail::within::multi_point_multi_point
+{};
+
+// P/L
+
+template <typename Point, typename Segment>
+struct covered_by<Point, Segment, point_tag, segment_tag>
+ : public detail::covered_by::use_point_in_geometry
+{};
+
+template <typename Point, typename Linestring>
+struct covered_by<Point, Linestring, point_tag, linestring_tag>
+ : public detail::covered_by::use_point_in_geometry
+{};
+
+template <typename Point, typename MultiLinestring>
+struct covered_by<Point, MultiLinestring, point_tag, multi_linestring_tag>
+ : public detail::covered_by::use_point_in_geometry
+{};
+
+template <typename MultiPoint, typename Segment>
+struct covered_by<MultiPoint, Segment, multi_point_tag, segment_tag>
+ : public detail::within::multi_point_single_geometry<false>
+{};
+
+template <typename MultiPoint, typename Linestring>
+struct covered_by<MultiPoint, Linestring, multi_point_tag, linestring_tag>
+ : public detail::within::multi_point_single_geometry<false>
+{};
+
+template <typename MultiPoint, typename MultiLinestring>
+struct covered_by<MultiPoint, MultiLinestring, multi_point_tag, multi_linestring_tag>
+ : public detail::within::multi_point_multi_geometry<false>
+{};
+
+// P/A
+
+template <typename Point, typename Ring>
+struct covered_by<Point, Ring, point_tag, ring_tag>
+ : public detail::covered_by::use_point_in_geometry
+{};
+
+template <typename Point, typename Polygon>
+struct covered_by<Point, Polygon, point_tag, polygon_tag>
+ : public detail::covered_by::use_point_in_geometry
+{};
+
+template <typename Point, typename MultiPolygon>
+struct covered_by<Point, MultiPolygon, point_tag, multi_polygon_tag>
+ : public detail::covered_by::use_point_in_geometry
+{};
+
+template <typename MultiPoint, typename Ring>
+struct covered_by<MultiPoint, Ring, multi_point_tag, ring_tag>
+ : public detail::within::multi_point_single_geometry<false>
+{};
+
+template <typename MultiPoint, typename Polygon>
+struct covered_by<MultiPoint, Polygon, multi_point_tag, polygon_tag>
+ : public detail::within::multi_point_single_geometry<false>
+{};
+
+template <typename MultiPoint, typename MultiPolygon>
+struct covered_by<MultiPoint, MultiPolygon, multi_point_tag, multi_polygon_tag>
+ : public detail::within::multi_point_multi_geometry<false>
+{};
+
+// L/L
+
+template <typename Linestring1, typename Linestring2>
+struct covered_by<Linestring1, Linestring2, linestring_tag, linestring_tag>
+ : public detail::covered_by::use_relate
+{};
+
+template <typename Linestring, typename MultiLinestring>
+struct covered_by<Linestring, MultiLinestring, linestring_tag, multi_linestring_tag>
+ : public detail::covered_by::use_relate
+{};
+
+template <typename MultiLinestring, typename Linestring>
+struct covered_by<MultiLinestring, Linestring, multi_linestring_tag, linestring_tag>
+ : public detail::covered_by::use_relate
+{};
+
+template <typename MultiLinestring1, typename MultiLinestring2>
+struct covered_by<MultiLinestring1, MultiLinestring2, multi_linestring_tag, multi_linestring_tag>
+ : public detail::covered_by::use_relate
+{};
+
+// L/A
+
+template <typename Linestring, typename Ring>
+struct covered_by<Linestring, Ring, linestring_tag, ring_tag>
+ : public detail::covered_by::use_relate
+{};
+
+template <typename MultiLinestring, typename Ring>
+struct covered_by<MultiLinestring, Ring, multi_linestring_tag, ring_tag>
+ : public detail::covered_by::use_relate
+{};
+
+template <typename Linestring, typename Polygon>
+struct covered_by<Linestring, Polygon, linestring_tag, polygon_tag>
+ : public detail::covered_by::use_relate
+{};
+
+template <typename MultiLinestring, typename Polygon>
+struct covered_by<MultiLinestring, Polygon, multi_linestring_tag, polygon_tag>
+ : public detail::covered_by::use_relate
+{};
+
+template <typename Linestring, typename MultiPolygon>
+struct covered_by<Linestring, MultiPolygon, linestring_tag, multi_polygon_tag>
+ : public detail::covered_by::use_relate
+{};
+
+template <typename MultiLinestring, typename MultiPolygon>
+struct covered_by<MultiLinestring, MultiPolygon, multi_linestring_tag, multi_polygon_tag>
+ : public detail::covered_by::use_relate
+{};
+
+// A/A
+
+template <typename Ring1, typename Ring2>
+struct covered_by<Ring1, Ring2, ring_tag, ring_tag>
+ : public detail::covered_by::use_relate
+{};
+
+template <typename Ring, typename Polygon>
+struct covered_by<Ring, Polygon, ring_tag, polygon_tag>
+ : public detail::covered_by::use_relate
+{};
+
+template <typename Polygon, typename Ring>
+struct covered_by<Polygon, Ring, polygon_tag, ring_tag>
+ : public detail::covered_by::use_relate
+{};
+
+template <typename Polygon1, typename Polygon2>
+struct covered_by<Polygon1, Polygon2, polygon_tag, polygon_tag>
+ : public detail::covered_by::use_relate
+{};
+
+template <typename Ring, typename MultiPolygon>
+struct covered_by<Ring, MultiPolygon, ring_tag, multi_polygon_tag>
+ : public detail::covered_by::use_relate
+{};
+
+template <typename MultiPolygon, typename Ring>
+struct covered_by<MultiPolygon, Ring, multi_polygon_tag, ring_tag>
+ : public detail::covered_by::use_relate
+{};
+
+template <typename Polygon, typename MultiPolygon>
+struct covered_by<Polygon, MultiPolygon, polygon_tag, multi_polygon_tag>
+ : public detail::covered_by::use_relate
+{};
+
+template <typename MultiPolygon, typename Polygon>
+struct covered_by<MultiPolygon, Polygon, multi_polygon_tag, polygon_tag>
+ : public detail::covered_by::use_relate
+{};
+
+template <typename MultiPolygon1, typename MultiPolygon2>
+struct covered_by<MultiPolygon1, MultiPolygon2, multi_polygon_tag, multi_polygon_tag>
+ : public detail::covered_by::use_relate
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_IMPLEMENTATION_HPP
diff --git a/boost/geometry/algorithms/detail/covered_by/interface.hpp b/boost/geometry/algorithms/detail/covered_by/interface.hpp
new file mode 100644
index 0000000000..6599078210
--- /dev/null
+++ b/boost/geometry/algorithms/detail/covered_by/interface.hpp
@@ -0,0 +1,261 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// This file was modified by Oracle on 2013, 2014, 2017.
+// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the 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_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_INTERFACE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_INTERFACE_HPP
+
+
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
+
+#include <boost/geometry/algorithms/detail/within/interface.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
+
+#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
+#include <boost/geometry/strategies/cartesian/box_in_box.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Tag1 = typename tag<Geometry1>::type,
+ typename Tag2 = typename tag<Geometry2>::type
+>
+struct covered_by
+ : not_implemented<Tag1, Tag2>
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+namespace resolve_strategy {
+
+struct covered_by
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ concepts::within::check
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
+ Strategy
+ >();
+ concepts::check<Geometry1 const>();
+ concepts::check<Geometry2 const>();
+ assert_dimension_equal<Geometry1, Geometry2>();
+
+ return dispatch::covered_by<Geometry1, Geometry2>::apply(geometry1,
+ geometry2,
+ strategy);
+ }
+
+ template <typename Geometry1, typename Geometry2>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ default_strategy)
+ {
+ typedef typename strategy::covered_by::services::default_strategy
+ <
+ Geometry1,
+ Geometry2
+ >::type strategy_type;
+
+ return covered_by::apply(geometry1, geometry2, strategy_type());
+ }
+};
+
+} // namespace resolve_strategy
+
+
+namespace resolve_variant {
+
+template <typename Geometry1, typename Geometry2>
+struct covered_by
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ return resolve_strategy::covered_by
+ ::apply(geometry1, geometry2, strategy);
+ }
+};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
+struct covered_by<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+{
+ template <typename Strategy>
+ struct visitor: boost::static_visitor<bool>
+ {
+ Geometry2 const& m_geometry2;
+ Strategy const& m_strategy;
+
+ visitor(Geometry2 const& geometry2, Strategy const& strategy)
+ : m_geometry2(geometry2), m_strategy(strategy) {}
+
+ template <typename Geometry1>
+ bool operator()(Geometry1 const& geometry1) const
+ {
+ return covered_by<Geometry1, Geometry2>
+ ::apply(geometry1, m_geometry2, m_strategy);
+ }
+ };
+
+ template <typename Strategy>
+ static inline bool
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
+ }
+};
+
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct covered_by<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ template <typename Strategy>
+ struct visitor: boost::static_visitor<bool>
+ {
+ Geometry1 const& m_geometry1;
+ Strategy const& m_strategy;
+
+ visitor(Geometry1 const& geometry1, Strategy const& strategy)
+ : m_geometry1(geometry1), m_strategy(strategy) {}
+
+ template <typename Geometry2>
+ bool operator()(Geometry2 const& geometry2) const
+ {
+ return covered_by<Geometry1, Geometry2>
+ ::apply(m_geometry1, geometry2, m_strategy);
+ }
+ };
+
+ template <typename Strategy>
+ static inline bool
+ apply(Geometry1 const& geometry1,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
+ Strategy const& strategy)
+ {
+ return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
+ }
+};
+
+template <
+ BOOST_VARIANT_ENUM_PARAMS(typename T1),
+ BOOST_VARIANT_ENUM_PARAMS(typename T2)
+>
+struct covered_by<
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
+>
+{
+ template <typename Strategy>
+ struct visitor: boost::static_visitor<bool>
+ {
+ Strategy const& m_strategy;
+
+ visitor(Strategy const& strategy): m_strategy(strategy) {}
+
+ template <typename Geometry1, typename Geometry2>
+ bool operator()(Geometry1 const& geometry1,
+ Geometry2 const& geometry2) const
+ {
+ return covered_by<Geometry1, Geometry2>
+ ::apply(geometry1, geometry2, m_strategy);
+ }
+ };
+
+ template <typename Strategy>
+ static inline bool
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
+ Strategy const& strategy)
+ {
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
+ }
+};
+
+} // namespace resolve_variant
+
+
+/*!
+\brief \brief_check12{is inside or on border}
+\ingroup covered_by
+\details \details_check12{covered_by, is inside or on border}.
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry which might be inside or on the border of the second geometry
+\param geometry2 \param_geometry which might cover the first geometry
+\return true if geometry1 is inside of or on the border of geometry2,
+ else false
+\note The default strategy is used for covered_by detection
+
+\qbk{[include reference/algorithms/covered_by.qbk]}
+
+ */
+template<typename Geometry1, typename Geometry2>
+inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ return resolve_variant::covered_by<Geometry1, Geometry2>
+ ::apply(geometry1, geometry2, default_strategy());
+}
+
+/*!
+\brief \brief_check12{is inside or on border} \brief_strategy
+\ingroup covered_by
+\details \details_check12{covered_by, is inside or on border}, \brief_strategy. \details_strategy_reasons
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry which might be inside or on the border of the second geometry
+\param geometry2 \param_geometry which might cover the first geometry
+\param strategy strategy to be used
+\return true if geometry1 is inside of or on the border of geometry2,
+ else false
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/covered_by.qbk]}
+
+*/
+template<typename Geometry1, typename Geometry2, typename Strategy>
+inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ return resolve_variant::covered_by<Geometry1, Geometry2>
+ ::apply(geometry1, geometry2, strategy);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_INTERFACE_HPP
diff --git a/boost/geometry/algorithms/detail/direction_code.hpp b/boost/geometry/algorithms/detail/direction_code.hpp
index 26d53ab4e5..c5c5221109 100644
--- a/boost/geometry/algorithms/detail/direction_code.hpp
+++ b/boost/geometry/algorithms/detail/direction_code.hpp
@@ -2,10 +2,11 @@
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2017.
+// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -17,14 +18,22 @@
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
+
+#include <boost/mpl/assert.hpp>
+
namespace boost { namespace geometry
{
+
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
+
+// TODO: remove
template <std::size_t Index, typename Point1, typename Point2>
inline int sign_of_difference(Point1 const& point1, Point2 const& point2)
{
@@ -37,35 +46,204 @@ inline int sign_of_difference(Point1 const& point1, Point2 const& point2)
}
-// Gives sense of direction for point p, collinear w.r.t. segment (a,b)
-// Returns -1 if p goes backward w.r.t (a,b), so goes from b in direction of a
-// Returns 1 if p goes forward, so extends (a,b)
-// Returns 0 if p is equal with b, or if (a,b) is degenerate
-// Note that it does not do any collinearity test, that should be done before
-template <typename Point1, typename Point2>
-inline int direction_code(Point1 const& segment_a, Point1 const& segment_b,
- const Point2& p)
+template <typename Point, typename CSTag = typename cs_tag<Point>::type>
+struct direction_code_impl
+{
+ BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_CS, (CSTag));
+};
+
+template <typename Point>
+struct direction_code_impl<Point, cartesian_tag>
{
- // Suppose segment = (4 3,4 4) and p =(4 2)
- // Then sign_a1 = 1 and sign_p1 = 1 -> goes backward -> return -1
+ template <typename Point1, typename Point2>
+ static inline int apply(Point1 const& segment_a, Point1 const& segment_b,
+ Point2 const& p)
+ {
+ typedef typename geometry::select_coordinate_type
+ <
+ Point1, Point2
+ >::type calc_t;
+
+ if ( (math::equals(geometry::get<0>(segment_b), geometry::get<0>(segment_a))
+ && math::equals(geometry::get<1>(segment_b), geometry::get<1>(segment_a)))
+ || (math::equals(geometry::get<0>(segment_b), geometry::get<0>(p))
+ && math::equals(geometry::get<1>(segment_b), geometry::get<1>(p))) )
+ {
+ return 0;
+ }
+
+ calc_t x1 = geometry::get<0>(segment_b) - geometry::get<0>(segment_a);
+ calc_t y1 = geometry::get<1>(segment_b) - geometry::get<1>(segment_a);
+ calc_t x2 = geometry::get<0>(segment_b) - geometry::get<0>(p);
+ calc_t y2 = geometry::get<1>(segment_b) - geometry::get<1>(p);
+
+ calc_t ax = (std::min)(math::abs(x1), math::abs(x2));
+ calc_t ay = (std::min)(math::abs(y1), math::abs(y2));
+
+ int s1 = 0, s2 = 0;
+ if (ax >= ay)
+ {
+ s1 = x1 > 0 ? 1 : -1;
+ s2 = x2 > 0 ? 1 : -1;
+ }
+ else
+ {
+ s1 = y1 > 0 ? 1 : -1;
+ s2 = y2 > 0 ? 1 : -1;
+ }
- int const sign_a0 = sign_of_difference<0>(segment_b, segment_a);
- int const sign_a1 = sign_of_difference<1>(segment_b, segment_a);
+ return s1 == s2 ? -1 : 1;
+ }
+};
- if (sign_a0 == 0 && sign_a1 == 0)
+template <typename Point>
+struct direction_code_impl<Point, spherical_equatorial_tag>
+{
+ template <typename Point1, typename Point2>
+ static inline int apply(Point1 const& segment_a, Point1 const& segment_b,
+ Point2 const& p)
{
- return 0;
+ typedef typename coordinate_type<Point1>::type coord1_t;
+ typedef typename coordinate_type<Point2>::type coord2_t;
+ typedef typename coordinate_system<Point1>::type::units units_t;
+ typedef typename coordinate_system<Point2>::type::units units2_t;
+ BOOST_MPL_ASSERT_MSG((boost::is_same<units_t, units2_t>::value),
+ NOT_IMPLEMENTED_FOR_DIFFERENT_UNITS,
+ (units_t, units2_t));
+
+ typedef typename geometry::select_coordinate_type <Point1, Point2>::type calc_t;
+ typedef math::detail::constants_on_spheroid<coord1_t, units_t> constants1;
+ typedef math::detail::constants_on_spheroid<coord2_t, units_t> constants2;
+ typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
+
+ coord1_t const a0 = geometry::get<0>(segment_a);
+ coord1_t const a1 = geometry::get<1>(segment_a);
+ coord1_t const b0 = geometry::get<0>(segment_b);
+ coord1_t const b1 = geometry::get<1>(segment_b);
+ coord2_t const p0 = geometry::get<0>(p);
+ coord2_t const p1 = geometry::get<1>(p);
+ coord1_t const pi_half1 = constants1::max_latitude();
+ coord2_t const pi_half2 = constants2::max_latitude();
+ calc_t const pi = constants::half_period();
+ calc_t const pi_half = constants::max_latitude();
+ calc_t const c0 = 0;
+
+ if ( (math::equals(b0, a0) && math::equals(b1, a1))
+ || (math::equals(b0, p0) && math::equals(b1, p1)) )
+ {
+ return 0;
+ }
+
+ bool const is_a_pole = math::equals(pi_half1, math::abs(a1));
+ bool const is_b_pole = math::equals(pi_half1, math::abs(b1));
+ bool const is_p_pole = math::equals(pi_half2, math::abs(p1));
+
+ if ( is_b_pole && ((is_a_pole && math::sign(b1) == math::sign(a1))
+ || (is_p_pole && math::sign(b1) == math::sign(p1))) )
+ {
+ return 0;
+ }
+
+ // NOTE: as opposed to the implementation for cartesian CS
+ // here point b is the origin
+
+ calc_t const dlon1 = math::longitude_distance_signed<units_t>(b0, a0);
+ calc_t const dlon2 = math::longitude_distance_signed<units_t>(b0, p0);
+
+ bool is_antilon1 = false, is_antilon2 = false;
+ calc_t const dlat1 = latitude_distance_signed(b1, a1, dlon1, pi, is_antilon1);
+ calc_t const dlat2 = latitude_distance_signed(b1, p1, dlon2, pi, is_antilon2);
+
+ calc_t mx = is_a_pole || is_b_pole || is_p_pole ?
+ c0 :
+ (std::min)(is_antilon1 ? c0 : math::abs(dlon1),
+ is_antilon2 ? c0 : math::abs(dlon2));
+ calc_t my = (std::min)(math::abs(dlat1),
+ math::abs(dlat2));
+
+ int s1 = 0, s2 = 0;
+ if (mx >= my)
+ {
+ s1 = dlon1 > 0 ? 1 : -1;
+ s2 = dlon2 > 0 ? 1 : -1;
+ }
+ else
+ {
+ s1 = dlat1 > 0 ? 1 : -1;
+ s2 = dlat2 > 0 ? 1 : -1;
+ }
+
+ return s1 == s2 ? -1 : 1;
}
- int const sign_p0 = sign_of_difference<0>(segment_b, p);
- int const sign_p1 = sign_of_difference<1>(segment_b, p);
+ template <typename T>
+ static inline T latitude_distance_signed(T const& lat1, T const& lat2, T const& lon_ds, T const& pi, bool & is_antilon)
+ {
+ T const c0 = 0;
+
+ T res = lat2 - lat1;
+
+ is_antilon = math::equals(math::abs(lon_ds), pi);
+ if (is_antilon)
+ {
+ res = lat2 + lat1;
+ if (res >= c0)
+ res = pi - res;
+ else
+ res = -pi - res;
+ }
- if (sign_p0 == 0 && sign_p1 == 0)
+ return res;
+ }
+};
+
+template <typename Point>
+struct direction_code_impl<Point, spherical_polar_tag>
+{
+ template <typename Point1, typename Point2>
+ static inline int apply(Point1 segment_a, Point1 segment_b,
+ Point2 p)
{
- return 0;
+ typedef math::detail::constants_on_spheroid
+ <
+ typename coordinate_type<Point1>::type,
+ typename coordinate_system<Point1>::type::units
+ > constants1;
+ typedef math::detail::constants_on_spheroid
+ <
+ typename coordinate_type<Point2>::type,
+ typename coordinate_system<Point2>::type::units
+ > constants2;
+
+ geometry::set<1>(segment_a,
+ constants1::max_latitude() - geometry::get<1>(segment_a));
+ geometry::set<1>(segment_b,
+ constants1::max_latitude() - geometry::get<1>(segment_b));
+ geometry::set<1>(p,
+ constants2::max_latitude() - geometry::get<1>(p));
+
+ return direction_code_impl
+ <
+ Point, spherical_equatorial_tag
+ >::apply(segment_a, segment_b, p);
}
+};
+
+template <typename Point>
+struct direction_code_impl<Point, geographic_tag>
+ : direction_code_impl<Point, spherical_equatorial_tag>
+{};
- return sign_a0 == sign_p0 && sign_a1 == sign_p1 ? -1 : 1;
+// Gives sense of direction for point p, collinear w.r.t. segment (a,b)
+// Returns -1 if p goes backward w.r.t (a,b), so goes from b in direction of a
+// Returns 1 if p goes forward, so extends (a,b)
+// Returns 0 if p is equal with b, or if (a,b) is degenerate
+// Note that it does not do any collinearity test, that should be done before
+template <typename Point1, typename Point2>
+inline int direction_code(Point1 const& segment_a, Point1 const& segment_b,
+ Point2 const& p)
+{
+ return direction_code_impl<Point1>::apply(segment_a, segment_b, p);
}
@@ -73,7 +251,6 @@ inline int direction_code(Point1 const& segment_a, Point1 const& segment_b,
#endif //DOXYGEN_NO_DETAIL
-
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP
diff --git a/boost/geometry/algorithms/detail/disjoint/box_box.hpp b/boost/geometry/algorithms/detail/disjoint/box_box.hpp
index f830f8161c..87618939b8 100644
--- a/boost/geometry/algorithms/detail/disjoint/box_box.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/box_box.hpp
@@ -121,9 +121,18 @@ struct box_box<Box1, Box2, 0, DimensionCount, spherical_tag>
// calculate positive longitude translation with b1_min as origin
calc_t const diff_min = math::longitude_distance_unsigned<units_t>(b1_min, b2_min);
calc_t const b2_min_transl = b1_min + diff_min; // always right of b1_min
+ calc_t b2_max_transl = b2_min_transl - constants::period() + diff2;
- if (b2_min_transl > b1_max // b2_min right of b1_max
- && b2_min_transl - constants::period() + diff2 < b1_min) // b2_max left of b1_min
+ // if the translation is too close then use the original point
+ // note that math::abs(b2_max_transl - b2_max) takes values very
+ // close to k*2*constants::period() for k=0,1,2,...
+ if (math::abs(b2_max_transl - b2_max) < constants::period() / 2)
+ {
+ b2_max_transl = b2_max;
+ }
+
+ if (b2_min_transl > b1_max // b2_min right of b1_max
+ && b2_max_transl < b1_min) // b2_max left of b1_min
{
return true;
}
diff --git a/boost/geometry/algorithms/detail/disjoint/implementation.hpp b/boost/geometry/algorithms/detail/disjoint/implementation.hpp
index d482c4a5a9..3a3d9865d1 100644
--- a/boost/geometry/algorithms/detail/disjoint/implementation.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/implementation.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2014.
-// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2017.
+// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
diff --git a/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
index 7c1a93cdb7..f8d3e3c593 100644
--- a/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2017, Oracle and/or its affiliates.
+// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -30,7 +31,9 @@
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/partition.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>
#include <boost/geometry/algorithms/detail/relate/less.hpp>
@@ -117,15 +120,21 @@ private:
}
};
- // TODO: After adding non-cartesian Segment envelope to the library
- // this policy should be modified to take envelope strategy.
+ template <typename EnvelopeStrategy>
struct expand_box_segment
{
+ explicit expand_box_segment(EnvelopeStrategy const& strategy)
+ : m_strategy(strategy)
+ {}
+
template <typename Box, typename Segment>
- static inline void apply(Box& total, Segment const& segment)
+ inline void apply(Box& total, Segment const& segment) const
{
- geometry::expand(total, geometry::return_envelope<Box>(segment));
+ geometry::expand(total,
+ geometry::return_envelope<Box>(segment, m_strategy));
}
+
+ EnvelopeStrategy const& m_strategy;
};
struct overlaps_box_point
@@ -134,32 +143,24 @@ private:
static inline bool apply(Box const& box, Point const& point)
{
// The default strategy is enough in this case
- typedef typename strategy::disjoint::services::default_strategy
- <
- Point, Box
- >::type strategy_type;
- return ! dispatch::disjoint<Point, Box>::apply(point, box, strategy_type());
+ return ! detail::disjoint::disjoint_point_box(point, box);
}
};
- // TODO: After implementing disjoint Segment/Box for non-cartesian geometries
- // this strategy should be passed here.
- // TODO: This Segment/Box strategy should somehow be derived from Point/Segment strategy
- // which by default is winding containing CS-specific side strategy
- // TODO: disjoint Segment/Box will be called in this case which may take
- // quite long in non-cartesian CS. So we should consider passing range of bounding boxes
- // of segments after calculating them once.
+ template <typename DisjointStrategy>
struct overlaps_box_segment
{
+ explicit overlaps_box_segment(DisjointStrategy const& strategy)
+ : m_strategy(strategy)
+ {}
+
template <typename Box, typename Segment>
- static inline bool apply(Box const& box, Segment const& segment)
+ inline bool apply(Box const& box, Segment const& segment) const
{
- typedef typename strategy::disjoint::services::default_strategy
- <
- Segment, Box
- >::type strategy_type;
- return ! dispatch::disjoint<Segment, Box>::apply(segment, box, strategy_type());
+ return ! dispatch::disjoint<Segment, Box>::apply(segment, box, m_strategy);
}
+
+ DisjointStrategy const& m_strategy;
};
template <typename PtSegStrategy>
@@ -172,13 +173,15 @@ private:
{}
template <typename Item1, typename Item2>
- inline void apply(Item1 const& item1, Item2 const& item2)
+ inline bool apply(Item1 const& item1, Item2 const& item2)
{
if (! m_intersection_found
&& ! dispatch::disjoint<Item1, Item2>::apply(item1, item2, m_strategy))
{
m_intersection_found = true;
+ return false;
}
+ return true;
}
inline bool intersection_found() const { return m_intersection_found; }
@@ -219,12 +222,22 @@ public:
{
item_visitor_type<Strategy> visitor(strategy);
+ typedef typename Strategy::envelope_strategy_type envelope_strategy_type;
+ typedef typename Strategy::disjoint_strategy_type disjoint_strategy_type;
+
+ // TODO: disjoint Segment/Box may be called in partition multiple times
+ // possibly for non-cartesian segments which could be slow. We should consider
+ // passing a range of bounding boxes of segments after calculating them once.
+ // Alternatively instead of a range of segments a range of Segment/Envelope pairs
+ // should be passed, where envelope would be lazily calculated when needed the first time
geometry::partition
<
geometry::model::box<typename point_type<MultiPoint>::type>
>::apply(multipoint, segment_range(linear), visitor,
- expand_box_point(), overlaps_box_point(),
- expand_box_segment(), overlaps_box_segment());
+ expand_box_point(),
+ overlaps_box_point(),
+ expand_box_segment<envelope_strategy_type>(strategy.get_envelope_strategy()),
+ overlaps_box_segment<disjoint_strategy_type>(strategy.get_disjoint_strategy()));
return ! visitor.intersection_found();
}
@@ -237,6 +250,176 @@ public:
};
+template <typename MultiPoint, typename SingleGeometry>
+class multi_point_single_geometry
+{
+public:
+ template <typename Strategy>
+ static inline bool apply(MultiPoint const& multi_point, SingleGeometry const& single_geometry, Strategy const& strategy)
+ {
+ typedef typename point_type<MultiPoint>::type point1_type;
+ typedef typename point_type<SingleGeometry>::type point2_type;
+ typedef model::box<point2_type> box2_type;
+
+ box2_type box2;
+ geometry::envelope(single_geometry, box2, strategy.get_envelope_strategy());
+ geometry::detail::expand_by_epsilon(box2);
+
+ typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
+ for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
+ {
+ // The default strategy is enough for Point/Box
+ if (! detail::disjoint::disjoint_point_box(*it, box2)
+ && ! dispatch::disjoint<point1_type, SingleGeometry>::apply(*it, single_geometry, strategy))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ template <typename Strategy>
+ static inline bool apply(SingleGeometry const& single_geometry, MultiPoint const& multi_point, Strategy const& strategy)
+ {
+ return apply(multi_point, single_geometry, strategy);
+ }
+};
+
+
+template <typename MultiPoint, typename MultiGeometry>
+class multi_point_multi_geometry
+{
+private:
+ struct expand_box_point
+ {
+ template <typename Box, typename Point>
+ static inline void apply(Box& total, Point const& point)
+ {
+ geometry::expand(total, point);
+ }
+ };
+
+ struct expand_box_box_pair
+ {
+ template <typename Box, typename BoxPair>
+ inline void apply(Box& total, BoxPair const& box_pair) const
+ {
+ geometry::expand(total, box_pair.first);
+ }
+ };
+
+ struct overlaps_box_point
+ {
+ template <typename Box, typename Point>
+ static inline bool apply(Box const& box, Point const& point)
+ {
+ // The default strategy is enough for Point/Box
+ return ! detail::disjoint::disjoint_point_box(point, box);
+ }
+ };
+
+ struct overlaps_box_box_pair
+ {
+ template <typename Box, typename BoxPair>
+ inline bool apply(Box const& box, BoxPair const& box_pair) const
+ {
+ // The default strategy is enough for Box/Box
+ return ! detail::disjoint::disjoint_box_box(box_pair.first, box);
+ }
+ };
+
+ template <typename PtSegStrategy>
+ class item_visitor_type
+ {
+ public:
+ item_visitor_type(MultiGeometry const& multi_geometry,
+ PtSegStrategy const& strategy)
+ : m_intersection_found(false)
+ , m_multi_geometry(multi_geometry)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Point, typename BoxPair>
+ inline bool apply(Point const& point, BoxPair const& box_pair)
+ {
+ typedef typename boost::range_value<MultiGeometry>::type single_type;
+
+ // The default strategy is enough for Point/Box
+ if (! m_intersection_found
+ && ! detail::disjoint::disjoint_point_box(point, box_pair.first)
+ && ! dispatch::disjoint<Point, single_type>::apply(point, range::at(m_multi_geometry, box_pair.second), m_strategy))
+ {
+ m_intersection_found = true;
+ return false;
+ }
+ return true;
+ }
+
+ inline bool intersection_found() const { return m_intersection_found; }
+
+ private:
+ bool m_intersection_found;
+ MultiGeometry const& m_multi_geometry;
+ PtSegStrategy const& m_strategy;
+ };
+ // structs for partition -- end
+
+public:
+ template <typename Strategy>
+ static inline bool apply(MultiPoint const& multi_point, MultiGeometry const& multi_geometry, Strategy const& strategy)
+ {
+ typedef typename point_type<MultiPoint>::type point1_type;
+ typedef typename point_type<MultiGeometry>::type point2_type;
+ typedef model::box<point1_type> box1_type;
+ typedef model::box<point2_type> box2_type;
+ typedef std::pair<box2_type, std::size_t> box_pair_type;
+
+ typename Strategy::envelope_strategy_type const
+ envelope_strategy = strategy.get_envelope_strategy();
+
+ std::size_t count2 = boost::size(multi_geometry);
+ std::vector<box_pair_type> boxes(count2);
+ for (std::size_t i = 0 ; i < count2 ; ++i)
+ {
+ geometry::envelope(range::at(multi_geometry, i), boxes[i].first, envelope_strategy);
+ geometry::detail::expand_by_epsilon(boxes[i].first);
+ boxes[i].second = i;
+ }
+
+ item_visitor_type<Strategy> visitor(multi_geometry, strategy);
+
+ geometry::partition
+ <
+ box1_type
+ >::apply(multi_point, boxes, visitor,
+ expand_box_point(),
+ overlaps_box_point(),
+ expand_box_box_pair(),
+ overlaps_box_box_pair());
+
+ return ! visitor.intersection_found();
+ }
+
+ template <typename Strategy>
+ static inline bool apply(MultiGeometry const& multi_geometry, MultiPoint const& multi_point, Strategy const& strategy)
+ {
+ return apply(multi_point, multi_geometry, strategy);
+ }
+};
+
+
+template <typename MultiPoint, typename Areal, typename Tag = typename tag<Areal>::type>
+struct multipoint_areal
+ : multi_point_single_geometry<MultiPoint, Areal>
+{};
+
+template <typename MultiPoint, typename Areal>
+struct multipoint_areal<MultiPoint, Areal, multi_polygon_tag>
+ : multi_point_multi_geometry<MultiPoint, Areal>
+{};
+
+
}} // namespace detail::disjoint
#endif // DOXYGEN_NO_DETAIL
@@ -321,6 +504,22 @@ struct disjoint
{};
+template <typename Areal, typename MultiPoint, std::size_t DimensionCount>
+struct disjoint
+ <
+ Areal, MultiPoint, DimensionCount, areal_tag, multi_point_tag, false
+ > : detail::disjoint::multipoint_areal<MultiPoint, Areal>
+{};
+
+
+template <typename MultiPoint, typename Areal, std::size_t DimensionCount>
+struct disjoint
+ <
+ MultiPoint, Areal, DimensionCount, multi_point_tag, areal_tag, false
+ > : detail::disjoint::multipoint_areal<MultiPoint, Areal>
+{};
+
+
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
diff --git a/boost/geometry/algorithms/detail/disjoint/segment_box.hpp b/boost/geometry/algorithms/detail/disjoint/segment_box.hpp
index c2741ce72c..fe849e1091 100644
--- a/boost/geometry/algorithms/detail/disjoint/segment_box.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/segment_box.hpp
@@ -8,8 +8,9 @@
// This file was modified by Oracle on 2013-2017.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -24,9 +25,18 @@
#include <cstddef>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
+#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
+#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
+#include <boost/geometry/formulas/vertex_longitude.hpp>
+
+#include <boost/geometry/geometries/box.hpp>
namespace boost { namespace geometry
{
@@ -36,10 +46,161 @@ namespace boost { namespace geometry
namespace detail { namespace disjoint
{
+template <typename CS_Tag>
+struct disjoint_segment_box_sphere_or_spheroid
+{
+private:
+
+ template <typename CT>
+ static inline void swap(CT& lon1,
+ CT& lat1,
+ CT& lon2,
+ CT& lat2)
+ {
+ std::swap(lon1, lon2);
+ std::swap(lat1, lat2);
+ }
+
+
+public:
+
+ template <typename Segment, typename Box, typename Strategy>
+ static inline bool apply(Segment const& segment,
+ Box const& box,
+ Strategy const& azimuth_strategy)
+ {
+ assert_dimension_equal<Segment, Box>();
+
+ typedef typename point_type<Segment>::type segment_point_type;
+ typedef typename cs_tag<Segment>::type segment_cs_type;
+
+ segment_point_type p0, p1;
+ geometry::detail::assign_point_from_index<0>(segment, p0);
+ geometry::detail::assign_point_from_index<1>(segment, p1);
+
+ // Simplest cases first
+
+ // Case 1: if box contains one of segment's endpoints then they are not disjoint
+ if (! disjoint_point_box(p0, box) || ! disjoint_point_box(p1, box))
+ {
+ return false;
+ }
+
+ // Case 2: disjoint if bounding boxes are disjoint
+
+ typedef typename coordinate_type<segment_point_type>::type CT;
+
+ segment_point_type p0_normalized =
+ geometry::detail::return_normalized<segment_point_type>(p0);
+ segment_point_type p1_normalized =
+ geometry::detail::return_normalized<segment_point_type>(p1);
+
+ CT lon1 = geometry::get_as_radian<0>(p0_normalized);
+ CT lat1 = geometry::get_as_radian<1>(p0_normalized);
+ CT lon2 = geometry::get_as_radian<0>(p1_normalized);
+ CT lat2 = geometry::get_as_radian<1>(p1_normalized);
+
+ if (lon1 > lon2)
+ {
+ swap(lon1, lat1, lon2, lat2);
+ }
+
+ //Compute alp1 outside envelope and pass it to envelope_segment_impl
+ //in order for it to be used later in the algorithm
+ CT alp1;
+
+ azimuth_strategy.apply(lon1, lat1, lon2, lat2, alp1);
+
+ geometry::model::box<segment_point_type> box_seg;
+
+ geometry::detail::envelope::envelope_segment_impl<segment_cs_type>
+ ::template apply<geometry::radian>(lon1, lat1,
+ lon2, lat2,
+ box_seg,
+ azimuth_strategy,
+ alp1);
+ if (disjoint_box_box(box, box_seg))
+ {
+ return true;
+ }
+
+ // Case 3: test intersection by comparing angles
+
+ CT a_b0, a_b1, a_b2, a_b3;
+
+ CT b_lon_min = geometry::get_as_radian<geometry::min_corner, 0>(box);
+ CT b_lat_min = geometry::get_as_radian<geometry::min_corner, 1>(box);
+ CT b_lon_max = geometry::get_as_radian<geometry::max_corner, 0>(box);
+ CT b_lat_max = geometry::get_as_radian<geometry::max_corner, 1>(box);
+
+ azimuth_strategy.apply(lon1, lat1, b_lon_min, b_lat_min, a_b0);
+ azimuth_strategy.apply(lon1, lat1, b_lon_max, b_lat_min, a_b1);
+ azimuth_strategy.apply(lon1, lat1, b_lon_min, b_lat_max, a_b2);
+ azimuth_strategy.apply(lon1, lat1, b_lon_max, b_lat_max, a_b3);
+
+ bool b0 = alp1 > a_b0;
+ bool b1 = alp1 > a_b1;
+ bool b2 = alp1 > a_b2;
+ bool b3 = alp1 > a_b3;
+
+ // if not all box points on the same side of the segment then
+ // there is an intersection
+ if (!(b0 && b1 && b2 && b3) && (b0 || b1 || b2 || b3))
+ {
+ return false;
+ }
+
+ // Case 4: The only intersection case not covered above is when all four
+ // points of the box are above (below) the segment in northern (southern)
+ // hemisphere. Then we have to compute the vertex of the segment
+
+ CT vertex_lat;
+ CT lat_sum = lat1 + lat2;
+
+ if ((b0 && b1 && b2 && b3 && lat_sum > CT(0))
+ || (!(b0 && b1 && b2 && b3) && lat_sum < CT(0)))
+ {
+ CT b_lat_below; //latitude of box closest to equator
+
+ if (lat_sum > CT(0))
+ {
+ vertex_lat = geometry::get_as_radian<geometry::max_corner, 1>(box_seg);
+ b_lat_below = b_lat_min;
+ } else {
+ vertex_lat = geometry::get_as_radian<geometry::min_corner, 1>(box_seg);
+ b_lat_below = b_lat_max;
+ }
+
+ //optimization TODO: computing the spherical longitude should suffice for
+ // the majority of cases
+ CT vertex_lon = geometry::formula::vertex_longitude<CT, CS_Tag>
+ ::apply(lon1, lat1,
+ lon2, lat2,
+ vertex_lat,
+ alp1,
+ azimuth_strategy);
+
+ // Check if the vertex point is within the band defined by the
+ // minimum and maximum longitude of the box; if yes, then return
+ // false if the point is above the min latitude of the box; return
+ // true in all other cases
+ if (vertex_lon >= b_lon_min && vertex_lon <= b_lon_max
+ && std::abs(vertex_lat) > std::abs(b_lat_below))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+};
+
struct disjoint_segment_box
{
template <typename Segment, typename Box, typename Strategy>
- static inline bool apply(Segment const& segment, Box const& box, Strategy const& strategy)
+ static inline bool apply(Segment const& segment,
+ Box const& box,
+ Strategy const& strategy)
{
return strategy.apply(segment, box);
}
@@ -56,7 +217,7 @@ namespace dispatch
template <typename Segment, typename Box, std::size_t DimensionCount>
struct disjoint<Segment, Box, DimensionCount, segment_tag, box_tag, false>
- : detail::disjoint::disjoint_segment_box
+ : detail::disjoint::disjoint_segment_box
{};
diff --git a/boost/geometry/algorithms/detail/envelope/segment.hpp b/boost/geometry/algorithms/detail/envelope/segment.hpp
index 7631e84883..7e37194968 100644
--- a/boost/geometry/algorithms/detail/envelope/segment.hpp
+++ b/boost/geometry/algorithms/detail/envelope/segment.hpp
@@ -130,19 +130,16 @@ private:
CalculationType& lat1,
CalculationType& lon2,
CalculationType& lat2,
+ CalculationType a1,
+ CalculationType a2,
Strategy const& strategy)
{
// coordinates are assumed to be in radians
BOOST_GEOMETRY_ASSERT(lon1 <= lon2);
- CalculationType lon1_rad = math::as_radian<Units>(lon1);
CalculationType lat1_rad = math::as_radian<Units>(lat1);
- CalculationType lon2_rad = math::as_radian<Units>(lon2);
CalculationType lat2_rad = math::as_radian<Units>(lat2);
- CalculationType a1, a2;
- strategy.apply(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a1, a2);
-
if (lat1 > lat2)
{
std::swap(lat1, lat2);
@@ -189,12 +186,11 @@ private:
}
}
- template <typename Units, typename CalculationType, typename Strategy>
- static inline void apply(CalculationType& lon1,
- CalculationType& lat1,
- CalculationType& lon2,
- CalculationType& lat2,
- Strategy const& strategy)
+ template <typename Units, typename CalculationType>
+ static inline void special_cases(CalculationType& lon1,
+ CalculationType& lat1,
+ CalculationType& lon2,
+ CalculationType& lat2)
{
typedef math::detail::constants_on_spheroid
<
@@ -249,23 +245,19 @@ private:
lon1 += constants::period();
swap(lon1, lat1, lon2, lat2);
}
-
- compute_box_corners<Units>(lon1, lat1, lon2, lat2, strategy);
}
-public:
- template <
- typename Units,
- typename CalculationType,
- typename Box,
- typename Strategy
- >
- static inline void apply(CalculationType lon1,
- CalculationType lat1,
- CalculationType lon2,
- CalculationType lat2,
- Box& mbr,
- Strategy const& strategy)
+ template
+ <
+ typename Units,
+ typename CalculationType,
+ typename Box
+ >
+ static inline void create_box(CalculationType lon1,
+ CalculationType lat1,
+ CalculationType lon2,
+ CalculationType lat2,
+ Box& mbr)
{
typedef typename coordinate_type<Box>::type box_coordinate_type;
@@ -276,8 +268,6 @@ public:
helper_box_type radian_mbr;
- apply<Units>(lon1, lat1, lon2, lat2, strategy);
-
geometry::set
<
min_corner, 0
@@ -300,6 +290,85 @@ public:
transform_units(radian_mbr, mbr);
}
+
+
+ template <typename Units, typename CalculationType, typename Strategy>
+ static inline void apply(CalculationType& lon1,
+ CalculationType& lat1,
+ CalculationType& lon2,
+ CalculationType& lat2,
+ Strategy const& strategy)
+ {
+ special_cases<Units>(lon1, lat1, lon2, lat2);
+
+ CalculationType lon1_rad = math::as_radian<Units>(lon1);
+ CalculationType lat1_rad = math::as_radian<Units>(lat1);
+ CalculationType lon2_rad = math::as_radian<Units>(lon2);
+ CalculationType lat2_rad = math::as_radian<Units>(lat2);
+ CalculationType alp1, alp2;
+ strategy.apply(lon1_rad, lat1_rad, lon2_rad, lat2_rad, alp1, alp2);
+
+ compute_box_corners<Units>(lon1, lat1, lon2, lat2, alp1, alp2, strategy);
+ }
+
+ template <typename Units, typename CalculationType, typename Strategy>
+ static inline void apply(CalculationType& lon1,
+ CalculationType& lat1,
+ CalculationType& lon2,
+ CalculationType& lat2,
+ Strategy const& strategy,
+ CalculationType alp1)
+ {
+ special_cases<Units>(lon1, lat1, lon2, lat2);
+
+ CalculationType lon1_rad = math::as_radian<Units>(lon1);
+ CalculationType lat1_rad = math::as_radian<Units>(lat1);
+ CalculationType lon2_rad = math::as_radian<Units>(lon2);
+ CalculationType lat2_rad = math::as_radian<Units>(lat2);
+ CalculationType alp2;
+ strategy.apply(lon2_rad, lat2_rad, lon1_rad, lat1_rad, alp2);
+ alp2 += math::pi<CalculationType>();
+
+ compute_box_corners<Units>(lon1, lat1, lon2, lat2, alp1, alp2, strategy);
+ }
+
+public:
+ template
+ <
+ typename Units,
+ typename CalculationType,
+ typename Box,
+ typename Strategy
+ >
+ static inline void apply(CalculationType lon1,
+ CalculationType lat1,
+ CalculationType lon2,
+ CalculationType lat2,
+ Box& mbr,
+ Strategy const& strategy)
+ {
+ apply<Units>(lon1, lat1, lon2, lat2, strategy);
+ create_box<Units>(lon1, lat1, lon2, lat2, mbr);
+ }
+
+ template
+ <
+ typename Units,
+ typename CalculationType,
+ typename Box,
+ typename Strategy
+ >
+ static inline void apply(CalculationType lon1,
+ CalculationType lat1,
+ CalculationType lon2,
+ CalculationType lat2,
+ Box& mbr,
+ Strategy const& strategy,
+ CalculationType alp1)
+ {
+ apply<Units>(lon1, lat1, lon2, lat2, strategy, alp1);
+ create_box<Units>(lon1, lat1, lon2, lat2, mbr);
+ }
};
template <std::size_t Dimension, std::size_t DimensionCount>
diff --git a/boost/geometry/algorithms/detail/equals/implementation.hpp b/boost/geometry/algorithms/detail/equals/implementation.hpp
new file mode 100644
index 0000000000..310059a427
--- /dev/null
+++ b/boost/geometry/algorithms/detail/equals/implementation.hpp
@@ -0,0 +1,397 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
+// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
+
+// This file was modified by Oracle on 2014, 2015, 2016, 2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the 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_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_IMPLEMENTATION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_IMPLEMENTATION_HPP
+
+
+#include <cstddef>
+#include <vector>
+
+#include <boost/range.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
+
+// For trivial checks
+#include <boost/geometry/algorithms/area.hpp>
+#include <boost/geometry/algorithms/length.hpp>
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+#include <boost/geometry/algorithms/detail/equals/collect_vectors.hpp>
+#include <boost/geometry/algorithms/detail/equals/interface.hpp>
+#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
+#include <boost/geometry/algorithms/relate.hpp>
+
+#include <boost/geometry/views/detail/indexed_point_view.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace equals
+{
+
+
+template
+<
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct point_point
+{
+ template <typename Point1, typename Point2, typename Strategy>
+ static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& strategy)
+ {
+ return ! detail::disjoint::point_point
+ <
+ Point1, Point2,
+ Dimension, DimensionCount
+ >::apply(point1, point2, strategy);
+ }
+};
+
+
+template
+<
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct box_box
+{
+ template <typename Box1, typename Box2, typename Strategy>
+ static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
+ {
+ if (!geometry::math::equals(get<min_corner, Dimension>(box1), get<min_corner, Dimension>(box2))
+ || !geometry::math::equals(get<max_corner, Dimension>(box1), get<max_corner, Dimension>(box2)))
+ {
+ return false;
+ }
+ return box_box<Dimension + 1, DimensionCount>::apply(box1, box2, strategy);
+ }
+};
+
+template <std::size_t DimensionCount>
+struct box_box<DimensionCount, DimensionCount>
+{
+ template <typename Box1, typename Box2, typename Strategy>
+ static inline bool apply(Box1 const& , Box2 const& , Strategy const& )
+ {
+ return true;
+ }
+};
+
+
+struct segment_segment
+{
+ template <typename Segment1, typename Segment2, typename Strategy>
+ static inline bool apply(Segment1 const& segment1, Segment2 const& segment2, Strategy const& )
+ {
+ return equals::equals_point_point(
+ indexed_point_view<Segment1 const, 0>(segment1),
+ indexed_point_view<Segment2 const, 0>(segment2) )
+ ? equals::equals_point_point(
+ indexed_point_view<Segment1 const, 1>(segment1),
+ indexed_point_view<Segment2 const, 1>(segment2) )
+ : ( equals::equals_point_point(
+ indexed_point_view<Segment1 const, 0>(segment1),
+ indexed_point_view<Segment2 const, 1>(segment2) )
+ && equals::equals_point_point(
+ indexed_point_view<Segment1 const, 1>(segment1),
+ indexed_point_view<Segment2 const, 0>(segment2) )
+ );
+ }
+};
+
+
+struct area_check
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ return geometry::math::equals(
+ geometry::area(geometry1,
+ strategy.template get_area_strategy<Geometry1>()),
+ geometry::area(geometry2,
+ strategy.template get_area_strategy<Geometry2>()));
+ }
+};
+
+
+struct length_check
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ return geometry::math::equals(
+ geometry::length(geometry1,
+ strategy.template get_distance_strategy<Geometry1>()),
+ geometry::length(geometry2,
+ strategy.template get_distance_strategy<Geometry2>()));
+ }
+};
+
+
+template <typename Geometry1, typename Geometry2, typename IntersectionStrategy>
+struct collected_vector
+{
+ typedef typename geometry::select_most_precise
+ <
+ typename select_coordinate_type
+ <
+ Geometry1, Geometry2
+ >::type,
+ double
+ >::type calculation_type;
+
+ typedef geometry::collected_vector
+ <
+ calculation_type,
+ Geometry1,
+ typename IntersectionStrategy::side_strategy_type
+ > type;
+};
+
+template <typename TrivialCheck>
+struct equals_by_collection
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ if (! TrivialCheck::apply(geometry1, geometry2, strategy))
+ {
+ return false;
+ }
+
+ typedef typename collected_vector
+ <
+ Geometry1, Geometry2, Strategy
+ >::type collected_vector_type;
+
+ std::vector<collected_vector_type> c1, c2;
+
+ geometry::collect_vectors(c1, geometry1);
+ geometry::collect_vectors(c2, geometry2);
+
+ if (boost::size(c1) != boost::size(c2))
+ {
+ return false;
+ }
+
+ std::sort(c1.begin(), c1.end());
+ std::sort(c2.begin(), c2.end());
+
+ // Just check if these vectors are equal.
+ return std::equal(c1.begin(), c1.end(), c2.begin());
+ }
+};
+
+template<typename Geometry1, typename Geometry2>
+struct equals_by_relate
+ : detail::relate::relate_impl
+ <
+ detail::de9im::static_mask_equals_type,
+ Geometry1,
+ Geometry2
+ >
+{};
+
+// If collect_vectors which is a SideStrategy-dispatched optimization
+// is implemented in a way consistent with the Intersection/Side Strategy
+// then collect_vectors is used, otherwise relate is used.
+// NOTE: the result could be conceptually different for invalid
+// geometries in different coordinate systems because collect_vectors
+// and relate treat invalid geometries differently.
+template<typename TrivialCheck>
+struct equals_by_collection_or_relate
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ typedef typename boost::is_base_of
+ <
+ nyi::not_implemented_tag,
+ typename collected_vector
+ <
+ Geometry1, Geometry2, Strategy
+ >::type
+ >::type enable_relate_type;
+
+ return apply(geometry1, geometry2, strategy, enable_relate_type());
+ }
+
+private:
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy,
+ boost::false_type /*enable_relate*/)
+ {
+ return equals_by_collection<TrivialCheck>::apply(geometry1, geometry2, strategy);
+ }
+
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy,
+ boost::true_type /*enable_relate*/)
+ {
+ return equals_by_relate<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
+ }
+};
+
+
+}} // namespace detail::equals
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename P1, typename P2, std::size_t DimensionCount, bool Reverse>
+struct equals<P1, P2, point_tag, point_tag, DimensionCount, Reverse>
+ : detail::equals::point_point<0, DimensionCount>
+{};
+
+template <typename MultiPoint1, typename MultiPoint2, std::size_t DimensionCount, bool Reverse>
+struct equals<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag, DimensionCount, Reverse>
+ : detail::equals::equals_by_relate<MultiPoint1, MultiPoint2>
+{};
+
+template <typename MultiPoint, typename Point, std::size_t DimensionCount, bool Reverse>
+struct equals<Point, MultiPoint, point_tag, multi_point_tag, DimensionCount, Reverse>
+ : detail::equals::equals_by_relate<Point, MultiPoint>
+{};
+
+template <typename Box1, typename Box2, std::size_t DimensionCount, bool Reverse>
+struct equals<Box1, Box2, box_tag, box_tag, DimensionCount, Reverse>
+ : detail::equals::box_box<0, DimensionCount>
+{};
+
+
+template <typename Ring1, typename Ring2, bool Reverse>
+struct equals<Ring1, Ring2, ring_tag, ring_tag, 2, Reverse>
+ : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
+{};
+
+
+template <typename Polygon1, typename Polygon2, bool Reverse>
+struct equals<Polygon1, Polygon2, polygon_tag, polygon_tag, 2, Reverse>
+ : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
+{};
+
+
+template <typename Polygon, typename Ring, bool Reverse>
+struct equals<Polygon, Ring, polygon_tag, ring_tag, 2, Reverse>
+ : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
+{};
+
+
+template <typename Ring, typename Box, bool Reverse>
+struct equals<Ring, Box, ring_tag, box_tag, 2, Reverse>
+ : detail::equals::equals_by_collection<detail::equals::area_check>
+{};
+
+
+template <typename Polygon, typename Box, bool Reverse>
+struct equals<Polygon, Box, polygon_tag, box_tag, 2, Reverse>
+ : detail::equals::equals_by_collection<detail::equals::area_check>
+{};
+
+template <typename Segment1, typename Segment2, std::size_t DimensionCount, bool Reverse>
+struct equals<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, Reverse>
+ : detail::equals::segment_segment
+{};
+
+template <typename LineString1, typename LineString2, bool Reverse>
+struct equals<LineString1, LineString2, linestring_tag, linestring_tag, 2, Reverse>
+ : detail::equals::equals_by_relate<LineString1, LineString2>
+{};
+
+template <typename LineString, typename MultiLineString, bool Reverse>
+struct equals<LineString, MultiLineString, linestring_tag, multi_linestring_tag, 2, Reverse>
+ : detail::equals::equals_by_relate<LineString, MultiLineString>
+{};
+
+template <typename MultiLineString1, typename MultiLineString2, bool Reverse>
+struct equals<MultiLineString1, MultiLineString2, multi_linestring_tag, multi_linestring_tag, 2, Reverse>
+ : detail::equals::equals_by_relate<MultiLineString1, MultiLineString2>
+{};
+
+
+template <typename MultiPolygon1, typename MultiPolygon2, bool Reverse>
+struct equals
+ <
+ MultiPolygon1, MultiPolygon2,
+ multi_polygon_tag, multi_polygon_tag,
+ 2,
+ Reverse
+ >
+ : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
+{};
+
+
+template <typename Polygon, typename MultiPolygon, bool Reverse>
+struct equals
+ <
+ Polygon, MultiPolygon,
+ polygon_tag, multi_polygon_tag,
+ 2,
+ Reverse
+ >
+ : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
+{};
+
+template <typename MultiPolygon, typename Ring, bool Reverse>
+struct equals
+ <
+ MultiPolygon, Ring,
+ multi_polygon_tag, ring_tag,
+ 2,
+ Reverse
+ >
+ : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_IMPLEMENTATION_HPP
+
diff --git a/boost/geometry/algorithms/detail/equals/interface.hpp b/boost/geometry/algorithms/detail/equals/interface.hpp
new file mode 100644
index 0000000000..eacf95e9fe
--- /dev/null
+++ b/boost/geometry/algorithms/detail/equals/interface.hpp
@@ -0,0 +1,317 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
+// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
+
+// This file was modified by Oracle on 2014, 2015, 2016, 2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the 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_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_INTERFACE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_INTERFACE_HPP
+
+
+#include <cstddef>
+
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
+
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/reverse_dispatch.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/strategies/relate.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Tag1 = typename tag<Geometry1>::type,
+ typename Tag2 = typename tag<Geometry2>::type,
+ std::size_t DimensionCount = dimension<Geometry1>::type::value,
+ bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
+>
+struct equals: not_implemented<Tag1, Tag2>
+{};
+
+
+// If reversal is needed, perform it
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1, typename Tag2,
+ std::size_t DimensionCount
+>
+struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true>
+ : equals<Geometry2, Geometry1, Tag2, Tag1, DimensionCount, false>
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
+ {
+ return equals
+ <
+ Geometry2, Geometry1,
+ Tag2, Tag1,
+ DimensionCount,
+ false
+ >::apply(g2, g1, strategy);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+namespace resolve_strategy
+{
+
+struct equals
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ return dispatch::equals
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy);
+ }
+
+ template <typename Geometry1, typename Geometry2>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ default_strategy)
+ {
+ typedef typename strategy::relate::services::default_strategy
+ <
+ Geometry1,
+ Geometry2
+ >::type strategy_type;
+
+ return dispatch::equals
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy_type());
+ }
+};
+
+} // namespace resolve_strategy
+
+
+namespace resolve_variant {
+
+template <typename Geometry1, typename Geometry2>
+struct equals
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ concepts::check_concepts_and_equal_dimensions
+ <
+ Geometry1 const,
+ Geometry2 const
+ >();
+
+ return resolve_strategy::equals
+ ::apply(geometry1, geometry2, strategy);
+ }
+};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
+struct equals<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+{
+ template <typename Strategy>
+ struct visitor: static_visitor<bool>
+ {
+ Geometry2 const& m_geometry2;
+ Strategy const& m_strategy;
+
+ visitor(Geometry2 const& geometry2, Strategy const& strategy)
+ : m_geometry2(geometry2)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry1>
+ inline bool operator()(Geometry1 const& geometry1) const
+ {
+ return equals<Geometry1, Geometry2>
+ ::apply(geometry1, m_geometry2, m_strategy);
+ }
+
+ };
+
+ template <typename Strategy>
+ static inline bool apply(
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy
+ )
+ {
+ return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
+ }
+};
+
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct equals<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ template <typename Strategy>
+ struct visitor: static_visitor<bool>
+ {
+ Geometry1 const& m_geometry1;
+ Strategy const& m_strategy;
+
+ visitor(Geometry1 const& geometry1, Strategy const& strategy)
+ : m_geometry1(geometry1)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry2>
+ inline bool operator()(Geometry2 const& geometry2) const
+ {
+ return equals<Geometry1, Geometry2>
+ ::apply(m_geometry1, geometry2, m_strategy);
+ }
+
+ };
+
+ template <typename Strategy>
+ static inline bool apply(
+ Geometry1 const& geometry1,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
+ Strategy const& strategy
+ )
+ {
+ return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
+ }
+};
+
+template <
+ BOOST_VARIANT_ENUM_PARAMS(typename T1),
+ BOOST_VARIANT_ENUM_PARAMS(typename T2)
+>
+struct equals<
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
+>
+{
+ template <typename Strategy>
+ struct visitor: static_visitor<bool>
+ {
+ Strategy const& m_strategy;
+
+ visitor(Strategy const& strategy)
+ : m_strategy(strategy)
+ {}
+
+ template <typename Geometry1, typename Geometry2>
+ inline bool operator()(Geometry1 const& geometry1,
+ Geometry2 const& geometry2) const
+ {
+ return equals<Geometry1, Geometry2>
+ ::apply(geometry1, geometry2, m_strategy);
+ }
+
+ };
+
+ template <typename Strategy>
+ static inline bool apply(
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
+ Strategy const& strategy
+ )
+ {
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
+ }
+};
+
+} // namespace resolve_variant
+
+
+/*!
+\brief \brief_check{are spatially equal}
+\details \details_check12{equals, is spatially equal}. Spatially equal means
+ that the same point set is included. A box can therefore be spatially equal
+ to a ring or a polygon, or a linestring can be spatially equal to a
+ multi-linestring or a segment. This only works theoretically, not all
+ combinations are implemented yet.
+\ingroup equals
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Strategy \tparam_strategy{Equals}
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param strategy \param_strategy{equals}
+\return \return_check2{are spatially equal}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/equals.qbk]}
+ */
+template <typename Geometry1, typename Geometry2, typename Strategy>
+inline bool equals(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ return resolve_variant::equals
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy);
+}
+
+
+/*!
+\brief \brief_check{are spatially equal}
+\details \details_check12{equals, is spatially equal}. Spatially equal means
+ that the same point set is included. A box can therefore be spatially equal
+ to a ring or a polygon, or a linestring can be spatially equal to a
+ multi-linestring or a segment. This only works theoretically, not all
+ combinations are implemented yet.
+\ingroup equals
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\return \return_check2{are spatially equal}
+
+\qbk{[include reference/algorithms/equals.qbk]}
+ */
+template <typename Geometry1, typename Geometry2>
+inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ return resolve_variant::equals<Geometry1, Geometry2>
+ ::apply(geometry1, geometry2, default_strategy());
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_INTERFACE_HPP
+
diff --git a/boost/geometry/algorithms/detail/extreme_points.hpp b/boost/geometry/algorithms/detail/extreme_points.hpp
index 65795cd05b..61e984ee3c 100644
--- a/boost/geometry/algorithms/detail/extreme_points.hpp
+++ b/boost/geometry/algorithms/detail/extreme_points.hpp
@@ -5,6 +5,11 @@
// Copyright (c) 2009-2013 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -117,12 +122,6 @@ struct extreme_points_on_ring
typedef typename boost::range_iterator<Ring const>::type range_iterator;
typedef typename geometry::point_type<Ring>::type point_type;
- typedef typename geometry::strategy::side::services::default_strategy
- <
- typename geometry::cs_tag<point_type>::type
- >::type side_strategy;
-
-
template <typename CirclingIterator, typename Points>
static inline bool extend(CirclingIterator& it,
std::size_t n,
@@ -214,10 +213,11 @@ struct extreme_points_on_ring
return true;
}
- template <typename Extremes, typename Intruders, typename CirclingIterator>
+ template <typename Extremes, typename Intruders, typename CirclingIterator, typename SideStrategy>
static inline void get_intruders(Ring const& ring, CirclingIterator left, CirclingIterator right,
Extremes const& extremes,
- Intruders& intruders)
+ Intruders& intruders,
+ SideStrategy const& strategy)
{
if (boost::size(extremes) < 3)
{
@@ -238,8 +238,8 @@ struct extreme_points_on_ring
if (coordinate > min_value && other_coordinate > other_min && other_coordinate < other_max)
{
int const factor = geometry::point_order<Ring>::value == geometry::clockwise ? 1 : -1;
- int const first_side = side_strategy::apply(*right, extremes.front(), *(extremes.begin() + 1)) * factor;
- int const last_side = side_strategy::apply(*right, *(extremes.rbegin() + 1), extremes.back()) * factor;
+ int const first_side = strategy.apply(*right, extremes.front(), *(extremes.begin() + 1)) * factor;
+ int const last_side = strategy.apply(*right, *(extremes.rbegin() + 1), extremes.back()) * factor;
// If not lying left from any of the extemes side
if (first_side != 1 && last_side != 1)
@@ -263,10 +263,11 @@ struct extreme_points_on_ring
}
}
- template <typename Extremes, typename Intruders>
+ template <typename Extremes, typename Intruders, typename SideStrategy>
static inline void get_intruders(Ring const& ring,
Extremes const& extremes,
- Intruders& intruders)
+ Intruders& intruders,
+ SideStrategy const& strategy)
{
std::size_t const n = boost::size(ring);
if (n >= 3)
@@ -275,12 +276,12 @@ struct extreme_points_on_ring
geometry::ever_circling_range_iterator<Ring const> right(ring);
++right;
- get_intruders(ring, left, right, extremes, intruders);
+ get_intruders(ring, left, right, extremes, intruders, strategy);
}
}
- template <typename Iterator>
- static inline bool right_turn(Ring const& ring, Iterator it)
+ template <typename Iterator, typename SideStrategy>
+ static inline bool right_turn(Ring const& ring, Iterator it, SideStrategy const& strategy)
{
typename std::iterator_traits<Iterator>::difference_type const index
= std::distance(boost::begin(ring), it);
@@ -295,8 +296,8 @@ struct extreme_points_on_ring
}
int const factor = geometry::point_order<Ring>::value == geometry::clockwise ? 1 : -1;
- int const first_side = side_strategy::apply(*(right - 1), *right, *left) * factor;
- int const last_side = side_strategy::apply(*left, *(left + 1), *right) * factor;
+ int const first_side = strategy.apply(*(right - 1), *right, *left) * factor;
+ int const last_side = strategy.apply(*left, *(left + 1), *right) * factor;
//std::cout << "Candidate at " << geometry::wkt(*it) << " first=" << first_side << " last=" << last_side << std::endl;
@@ -306,8 +307,11 @@ struct extreme_points_on_ring
// Gets the extreme segments (top point plus neighbouring points), plus intruders, if any, on the same ring
- template <typename Extremes, typename Intruders>
- static inline bool apply(Ring const& ring, Extremes& extremes, Intruders& intruders)
+ template <typename Extremes, typename Intruders, typename SideStrategy>
+ static inline bool apply(Ring const& ring,
+ Extremes& extremes,
+ Intruders& intruders,
+ SideStrategy const& strategy)
{
std::size_t const n = boost::size(ring);
if (n < 3)
@@ -321,7 +325,7 @@ struct extreme_points_on_ring
compare<Dimension> smaller;
for (range_iterator it = max_it + 1; it != boost::end(ring); ++it)
{
- if (smaller(*max_it, *it) && right_turn(ring, it))
+ if (smaller(*max_it, *it) && right_turn(ring, it, strategy))
{
max_it = it;
}
@@ -365,7 +369,7 @@ struct extreme_points_on_ring
std::copy(points.begin(), points.end(), std::back_inserter(extremes));
- get_intruders(ring, left, right, extremes, intruders);
+ get_intruders(ring, left, right, extremes, intruders, strategy);
return true;
}
@@ -403,8 +407,9 @@ struct extreme_points<Ring, Dimension, ring_tag>
template<typename Polygon, std::size_t Dimension>
struct extreme_points<Polygon, Dimension, polygon_tag>
{
- template <typename Extremes, typename Intruders>
- static inline bool apply(Polygon const& polygon, Extremes& extremes, Intruders& intruders)
+ template <typename Extremes, typename Intruders, typename SideStrategy>
+ static inline bool apply(Polygon const& polygon, Extremes& extremes, Intruders& intruders,
+ SideStrategy const& strategy)
{
typedef typename geometry::ring_type<Polygon>::type ring_type;
typedef detail::extreme_points::extreme_points_on_ring
@@ -412,7 +417,8 @@ struct extreme_points<Polygon, Dimension, polygon_tag>
ring_type, Dimension
> ring_implementation;
- if (! ring_implementation::apply(geometry::exterior_ring(polygon), extremes, intruders))
+ if (! ring_implementation::apply(geometry::exterior_ring(polygon),
+ extremes, intruders, strategy))
{
return false;
}
@@ -423,7 +429,7 @@ struct extreme_points<Polygon, Dimension, polygon_tag>
for (typename detail::interior_iterator<Polygon const>::type
it = boost::begin(rings); it != boost::end(rings); ++it)
{
- ring_implementation::get_intruders(*it, extremes, intruders);
+ ring_implementation::get_intruders(*it, extremes, intruders, strategy);
}
return true;
@@ -433,8 +439,9 @@ struct extreme_points<Polygon, Dimension, polygon_tag>
template<typename Box>
struct extreme_points<Box, 1, box_tag>
{
- template <typename Extremes, typename Intruders>
- static inline bool apply(Box const& box, Extremes& extremes, Intruders& )
+ template <typename Extremes, typename Intruders, typename SideStrategy>
+ static inline bool apply(Box const& box, Extremes& extremes, Intruders& ,
+ SideStrategy const& )
{
extremes.resize(4);
geometry::detail::assign_box_corners_oriented<false>(box, extremes);
@@ -446,8 +453,9 @@ struct extreme_points<Box, 1, box_tag>
template<typename Box>
struct extreme_points<Box, 0, box_tag>
{
- template <typename Extremes, typename Intruders>
- static inline bool apply(Box const& box, Extremes& extremes, Intruders& )
+ template <typename Extremes, typename Intruders, typename SideStrategy>
+ static inline bool apply(Box const& box, Extremes& extremes, Intruders& ,
+ SideStrategy const& )
{
extremes.resize(4);
geometry::detail::assign_box_corners_oriented<false>(box, extremes);
@@ -460,8 +468,9 @@ struct extreme_points<Box, 0, box_tag>
template<typename MultiPolygon, std::size_t Dimension>
struct extreme_points<MultiPolygon, Dimension, multi_polygon_tag>
{
- template <typename Extremes, typename Intruders>
- static inline bool apply(MultiPolygon const& multi, Extremes& extremes, Intruders& intruders)
+ template <typename Extremes, typename Intruders, typename SideStrategy>
+ static inline bool apply(MultiPolygon const& multi, Extremes& extremes,
+ Intruders& intruders, SideStrategy const& strategy)
{
// Get one for the very first polygon, that is (for the moment) enough.
// It is not guaranteed the "extreme" then, but for the current purpose
@@ -473,7 +482,7 @@ struct extreme_points<MultiPolygon, Dimension, multi_polygon_tag>
typename boost::range_value<MultiPolygon const>::type,
Dimension,
polygon_tag
- >::apply(*boost::begin(multi), extremes, intruders);
+ >::apply(*boost::begin(multi), extremes, intruders, strategy);
}
return false;
@@ -489,8 +498,18 @@ struct extreme_points<MultiPolygon, Dimension, multi_polygon_tag>
for Edge=0 in dimension 0, the right side)
\note We could specify a strategy (less/greater) to get bottom/left side too. However, until now we don't need that.
*/
-template <std::size_t Edge, typename Geometry, typename Extremes, typename Intruders>
-inline bool extreme_points(Geometry const& geometry, Extremes& extremes, Intruders& intruders)
+template
+<
+ std::size_t Edge,
+ typename Geometry,
+ typename Extremes,
+ typename Intruders,
+ typename SideStrategy
+>
+inline bool extreme_points(Geometry const& geometry,
+ Extremes& extremes,
+ Intruders& intruders,
+ SideStrategy const& strategy)
{
concepts::check<Geometry const>();
@@ -509,7 +528,11 @@ inline bool extreme_points(Geometry const& geometry, Extremes& extremes, Intrude
const
>();
- return dispatch::extreme_points<Geometry, Edge>::apply(geometry, extremes, intruders);
+ return dispatch::extreme_points
+ <
+ Geometry,
+ Edge
+ >::apply(geometry, extremes, intruders, strategy);
}
diff --git a/boost/geometry/algorithms/detail/get_left_turns.hpp b/boost/geometry/algorithms/detail/get_left_turns.hpp
index 95ab98c236..e9f6a50859 100644
--- a/boost/geometry/algorithms/detail/get_left_turns.hpp
+++ b/boost/geometry/algorithms/detail/get_left_turns.hpp
@@ -2,6 +2,11 @@
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -60,17 +65,14 @@ inline int squared_length(Vector const& vector)
}
-template <typename Point>
+template <typename Point, typename SideStrategy>
struct angle_less
{
typedef Point vector_type;
- typedef typename strategy::side::services::default_strategy
- <
- typename cs_tag<Point>::type
- >::type side_strategy_type;
- angle_less(Point const& origin)
+ angle_less(Point const& origin, SideStrategy const& strategy)
: m_origin(origin)
+ , m_strategy(strategy)
{}
template <typename Angle>
@@ -89,8 +91,7 @@ struct angle_less
return quadrant_p < quadrant_q;
}
// Same quadrant, check if p is located left of q
- int const side = side_strategy_type::apply(m_origin, q.point,
- p.point);
+ int const side = m_strategy.apply(m_origin, q.point, p.point);
if (side != 0)
{
return side == 1;
@@ -114,19 +115,17 @@ struct angle_less
private:
Point m_origin;
+ SideStrategy m_strategy;
};
-template <typename Point>
+template <typename Point, typename SideStrategy>
struct angle_equal_to
{
typedef Point vector_type;
- typedef typename strategy::side::services::default_strategy
- <
- typename cs_tag<Point>::type
- >::type side_strategy_type;
-
- inline angle_equal_to(Point const& origin)
+
+ inline angle_equal_to(Point const& origin, SideStrategy const& strategy)
: m_origin(origin)
+ , m_strategy(strategy)
{}
template <typename Angle>
@@ -143,13 +142,13 @@ struct angle_equal_to
return false;
}
// Same quadrant, check if p/q are collinear
- int const side = side_strategy_type::apply(m_origin, q.point,
- p.point);
+ int const side = m_strategy.apply(m_origin, q.point, p.point);
return side == 0;
}
private:
Point m_origin;
+ SideStrategy m_strategy;
};
template <typename AngleCollection, typename Turns>
@@ -193,13 +192,14 @@ inline void get_left_turns(AngleCollection const& sorted_angles,
//! Returns the number of clusters
-template <typename Point, typename AngleCollection>
-inline std::size_t assign_cluster_indices(AngleCollection& sorted, Point const& origin)
+template <typename Point, typename AngleCollection, typename SideStrategy>
+inline std::size_t assign_cluster_indices(AngleCollection& sorted, Point const& origin,
+ SideStrategy const& strategy)
{
// Assign same cluster_index for all turns in same direction
BOOST_GEOMETRY_ASSERT(boost::size(sorted) >= 4u);
- angle_equal_to<Point> comparator(origin);
+ angle_equal_to<Point, SideStrategy> comparator(origin, strategy);
typename boost::range_iterator<AngleCollection>::type it = sorted.begin();
std::size_t cluster_index = 0;
diff --git a/boost/geometry/algorithms/detail/has_self_intersections.hpp b/boost/geometry/algorithms/detail/has_self_intersections.hpp
index 9a388a4d80..c34bb217a6 100644
--- a/boost/geometry/algorithms/detail/has_self_intersections.hpp
+++ b/boost/geometry/algorithms/detail/has_self_intersections.hpp
@@ -81,7 +81,7 @@ inline bool has_self_intersections(Geometry const& geometry,
std::deque<turn_info> turns;
detail::disjoint::disjoint_interrupt_policy policy;
- geometry::self_turns<detail::overlay::assign_null_policy>(geometry, strategy, robust_policy, turns, policy);
+ detail::self_get_turn_points::self_turns<false, detail::overlay::assign_null_policy>(geometry, strategy, robust_policy, turns, policy);
#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS
bool first = true;
diff --git a/boost/geometry/algorithms/detail/intersects/implementation.hpp b/boost/geometry/algorithms/detail/intersects/implementation.hpp
new file mode 100644
index 0000000000..2379168e83
--- /dev/null
+++ b/boost/geometry/algorithms/detail/intersects/implementation.hpp
@@ -0,0 +1,88 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
+
+// This file was modified by Oracle on 2013-2017.
+// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the 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_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTS_IMPLEMENTATION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTS_IMPLEMENTATION_HPP
+
+
+#include <deque>
+
+#include <boost/geometry/algorithms/detail/intersects/interface.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/implementation.hpp>
+
+#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
+#include <boost/geometry/policies/disjoint_interrupt_policy.hpp>
+#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
+#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
+
+#include <boost/geometry/strategies/relate.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace intersects
+{
+
+template <typename Geometry>
+struct self_intersects
+{
+ static bool apply(Geometry const& geometry)
+ {
+ concepts::check<Geometry const>();
+
+ typedef typename geometry::point_type<Geometry>::type point_type;
+ typedef typename strategy::relate::services::default_strategy
+ <
+ Geometry, Geometry
+ >::type strategy_type;
+ typedef detail::no_rescale_policy rescale_policy_type;
+
+ typedef detail::overlay::turn_info
+ <
+ point_type,
+ typename segment_ratio_type<point_type, rescale_policy_type>::type
+ > turn_info;
+
+ std::deque<turn_info> turns;
+
+ typedef detail::overlay::get_turn_info
+ <
+ detail::overlay::assign_null_policy
+ > turn_policy;
+
+ strategy_type strategy;
+ rescale_policy_type robust_policy;
+
+ detail::disjoint::disjoint_interrupt_policy policy;
+ detail::self_get_turn_points::get_turns
+ <
+ false, turn_policy
+ >::apply(geometry, strategy, robust_policy, turns, policy, 0);
+ return policy.has_intersections;
+ }
+};
+
+}} // namespace detail::intersects
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTS_IMPLEMENTATION_HPP
diff --git a/boost/geometry/algorithms/detail/intersects/interface.hpp b/boost/geometry/algorithms/detail/intersects/interface.hpp
new file mode 100644
index 0000000000..8940a426f3
--- /dev/null
+++ b/boost/geometry/algorithms/detail/intersects/interface.hpp
@@ -0,0 +1,115 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
+
+// This file was modified by Oracle on 2013-2017.
+// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the 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_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTS_INTERFACE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTS_INTERFACE_HPP
+
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/detail/disjoint/interface.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace intersects
+{
+
+// Forward declaration
+template <typename Geometry>
+struct self_intersects;
+
+}} // namespace detail::intersects
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+\brief \brief_check{has at least one intersection (crossing or self-tangency)}
+\note This function can be called for one geometry (self-intersection) and
+ also for two geometries (intersection)
+\ingroup intersects
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry
+\return \return_check{is self-intersecting}
+
+\qbk{distinguish,one geometry}
+\qbk{[def __one_parameter__]}
+\qbk{[include reference/algorithms/intersects.qbk]}
+*/
+template <typename Geometry>
+inline bool intersects(Geometry const& geometry)
+{
+ return detail::intersects::self_intersects<Geometry>::apply(geometry);
+}
+
+
+/*!
+\brief \brief_check2{have at least one intersection}
+\ingroup intersects
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Strategy \tparam_strategy{Intersects}
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param strategy \param_strategy{intersects}
+\return \return_check2{intersect each other}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/intersects.qbk]}
+ */
+template <typename Geometry1, typename Geometry2, typename Strategy>
+inline bool intersects(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ concepts::check<Geometry1 const>();
+ concepts::check<Geometry2 const>();
+
+ return ! geometry::disjoint(geometry1, geometry2, strategy);
+}
+
+
+/*!
+\brief \brief_check2{have at least one intersection}
+\ingroup intersects
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\return \return_check2{intersect each other}
+
+\qbk{distinguish,two geometries}
+\qbk{[include reference/algorithms/intersects.qbk]}
+ */
+template <typename Geometry1, typename Geometry2>
+inline bool intersects(Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ concepts::check<Geometry1 const>();
+ concepts::check<Geometry2 const>();
+
+ return ! geometry::disjoint(geometry1, geometry2);
+}
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTS_INTERFACE_HPP
diff --git a/boost/geometry/algorithms/detail/is_simple/linear.hpp b/boost/geometry/algorithms/detail/is_simple/linear.hpp
index 52b9d9d1c8..5acf56c5b1 100644
--- a/boost/geometry/algorithms/detail/is_simple/linear.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/linear.hpp
@@ -219,12 +219,12 @@ inline bool has_self_intersections(Linear const& linear, Strategy const& strateg
detail::self_get_turn_points::get_turns
<
- turn_policy
+ false, turn_policy
>::apply(linear,
strategy,
detail::no_rescale_policy(),
turns,
- interrupt_policy);
+ interrupt_policy, 0);
detail::is_valid::debug_print_turns(turns.begin(), turns.end());
debug_print_boundary_points(linear);
@@ -236,7 +236,9 @@ inline bool has_self_intersections(Linear const& linear, Strategy const& strateg
template <typename Linestring, bool CheckSelfIntersections = true>
struct is_simple_linestring
{
- static inline bool apply(Linestring const& linestring)
+ template <typename Strategy>
+ static inline bool apply(Linestring const& linestring,
+ Strategy const& strategy)
{
simplicity_failure_policy policy;
return ! boost::empty(linestring)
@@ -247,7 +249,7 @@ struct is_simple_linestring
&& ! detail::is_valid::has_spikes
<
Linestring, closed
- >::apply(linestring, policy);
+ >::apply(linestring, policy, strategy.get_side_strategy());
}
};
@@ -258,7 +260,10 @@ struct is_simple_linestring<Linestring, true>
static inline bool apply(Linestring const& linestring,
Strategy const& strategy)
{
- return is_simple_linestring<Linestring, false>::apply(linestring)
+ return is_simple_linestring
+ <
+ Linestring, false
+ >::apply(linestring, strategy)
&& ! has_self_intersections(linestring, strategy);
}
};
@@ -267,23 +272,44 @@ struct is_simple_linestring<Linestring, true>
template <typename MultiLinestring>
struct is_simple_multilinestring
{
+private:
+ template <typename Strategy>
+ struct per_linestring
+ {
+ per_linestring(Strategy const& strategy)
+ : m_strategy(strategy)
+ {}
+
+ template <typename Linestring>
+ inline bool apply(Linestring const& linestring) const
+ {
+ return detail::is_simple::is_simple_linestring
+ <
+ Linestring,
+ false // do not compute self-intersections
+ >::apply(linestring, m_strategy);
+ }
+
+ Strategy const& m_strategy;
+ };
+
+public:
template <typename Strategy>
static inline bool apply(MultiLinestring const& multilinestring,
Strategy const& strategy)
{
+ typedef per_linestring<Strategy> per_ls;
+
// check each of the linestrings for simplicity
// but do not compute self-intersections yet; these will be
// computed for the entire multilinestring
if ( ! detail::check_iterator_range
<
- is_simple_linestring
- <
- typename boost::range_value<MultiLinestring>::type,
- false // do not compute self-intersections
- >,
+ per_ls, // do not compute self-intersections
true // allow empty multilinestring
>::apply(boost::begin(multilinestring),
- boost::end(multilinestring))
+ boost::end(multilinestring),
+ per_ls(strategy))
)
{
return false;
diff --git a/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp b/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp
index aa90e52db6..96efec79cd 100644
--- a/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp
@@ -1,8 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -91,8 +92,9 @@ struct has_spikes
return std::find_if(second, last, not_equal(*first));
}
- template <typename VisitPolicy>
- static inline bool apply(Range const& range, VisitPolicy& visitor)
+ template <typename VisitPolicy, typename SideStrategy>
+ static inline bool apply(Range const& range, VisitPolicy& visitor,
+ SideStrategy const& strategy)
{
boost::ignore_unused(visitor);
@@ -124,9 +126,8 @@ struct has_spikes
while (next != boost::end(view))
{
- if ( geometry::detail::point_is_spike_or_equal(*prev,
- *next,
- *cur) )
+ if ( geometry::detail::point_is_spike_or_equal(*prev, *next, *cur,
+ strategy) )
{
return
! visitor.template apply<failure_spikes>(is_linear, *cur);
@@ -146,7 +147,7 @@ struct has_spikes
boost::rend(view));
iterator next = find_different_from_first(cur, boost::end(view));
- if (detail::point_is_spike_or_equal(*prev, *next, *cur))
+ if (detail::point_is_spike_or_equal(*prev, *next, *cur, strategy))
{
return
! visitor.template apply<failure_spikes>(is_linear, *cur);
diff --git a/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp b/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp
index b91dc6a697..b36e9f38b7 100644
--- a/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp
@@ -86,7 +86,7 @@ public:
IsAcceptableTurn
> interrupt_policy;
- geometry::self_turns<turn_policy>(geometry,
+ detail::self_get_turn_points::self_turns<false, turn_policy>(geometry,
strategy,
robust_policy,
turns,
diff --git a/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp b/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp
index 0d80d6f6c0..fccc0ffdb7 100644
--- a/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp
@@ -138,10 +138,17 @@ public:
}
operation_type const op = acceptable_operation<MultiPolygon>::value;
+ if ( base::check_turn(turn, method_touch_interior, op)
+ || base::check_turn(turn, method_touch, op))
+ {
+ return true;
+ }
- return base::check_turn(turn, method_touch_interior, op)
- || base::check_turn(turn, method_touch, op)
- ;
+ // Turn is acceptable only in case of a touch(interior) and both lines
+ // (polygons) do not cross
+ return (turn.method == method_touch
+ || turn.method == method_touch_interior)
+ && turn.touch_only;
}
};
diff --git a/boost/geometry/algorithms/detail/is_valid/linear.hpp b/boost/geometry/algorithms/detail/is_valid/linear.hpp
index 6bc6b86cf8..39cb36ef5b 100644
--- a/boost/geometry/algorithms/detail/is_valid/linear.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/linear.hpp
@@ -43,9 +43,10 @@ namespace detail { namespace is_valid
template <typename Linestring>
struct is_valid_linestring
{
- template <typename VisitPolicy>
+ template <typename VisitPolicy, typename Strategy>
static inline bool apply(Linestring const& linestring,
- VisitPolicy& visitor)
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
if (has_invalid_coordinate<Linestring>::apply(linestring, visitor))
{
@@ -75,15 +76,12 @@ struct is_valid_linestring
{
return visitor.template apply<no_failure>();
}
- return ! has_spikes<Linestring, closed>::apply(linestring, visitor);
- }
- template <typename VisitPolicy, typename Strategy>
- static inline bool apply(Linestring const& linestring,
- VisitPolicy& visitor,
- Strategy const&)
- {
- return apply(linestring, visitor);
+ return ! has_spikes
+ <
+ Linestring, closed
+ >::apply(linestring, visitor,
+ strategy.get_side_strategy());
}
};
@@ -132,10 +130,13 @@ class is_valid
>
{
private:
- template <typename VisitPolicy>
+ template <typename VisitPolicy, typename Strategy>
struct per_linestring
{
- per_linestring(VisitPolicy& policy) : m_policy(policy) {}
+ per_linestring(VisitPolicy& policy, Strategy const& strategy)
+ : m_policy(policy)
+ , m_strategy(strategy)
+ {}
template <typename Linestring>
inline bool apply(Linestring const& linestring) const
@@ -143,17 +144,18 @@ private:
return detail::is_valid::is_valid_linestring
<
Linestring
- >::apply(linestring, m_policy);
+ >::apply(linestring, m_policy, m_strategy);
}
VisitPolicy& m_policy;
+ Strategy const& m_strategy;
};
public:
template <typename VisitPolicy, typename Strategy>
static inline bool apply(MultiLinestring const& multilinestring,
VisitPolicy& visitor,
- Strategy const&)
+ Strategy const& strategy)
{
if (BOOST_GEOMETRY_CONDITION(
AllowEmptyMultiGeometries && boost::empty(multilinestring)))
@@ -161,13 +163,15 @@ public:
return visitor.template apply<no_failure>();
}
+ typedef per_linestring<VisitPolicy, Strategy> per_ls;
+
return detail::check_iterator_range
<
- per_linestring<VisitPolicy>,
+ per_ls,
false // do not check for empty multilinestring (done above)
>::apply(boost::begin(multilinestring),
boost::end(multilinestring),
- per_linestring<VisitPolicy>(visitor));
+ per_ls(visitor, strategy));
}
};
diff --git a/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp b/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
index 84dacc57f1..ed24b13810 100644
--- a/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
@@ -76,45 +76,66 @@ private:
<
typename PolygonIterator,
typename TurnIterator,
- typename VisitPolicy
+ typename VisitPolicy,
+ typename Strategy
>
static inline
bool are_polygon_interiors_disjoint(PolygonIterator polygons_first,
PolygonIterator polygons_beyond,
TurnIterator turns_first,
TurnIterator turns_beyond,
- VisitPolicy& visitor)
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
boost::ignore_unused(visitor);
- // collect all polygons that have turns
+ // collect all polygons that have crossing turns
std::set<signed_size_type> multi_indices;
for (TurnIterator tit = turns_first; tit != turns_beyond; ++tit)
{
- multi_indices.insert(tit->operations[0].seg_id.multi_index);
- multi_indices.insert(tit->operations[1].seg_id.multi_index);
+ if (! tit->touch_only)
+ {
+ multi_indices.insert(tit->operations[0].seg_id.multi_index);
+ multi_indices.insert(tit->operations[1].seg_id.multi_index);
+ }
}
+ typedef geometry::model::box<typename point_type<MultiPolygon>::type> box_type;
+ typedef typename base::template partition_item<PolygonIterator, box_type> item_type;
+
// put polygon iterators without turns in a vector
- std::vector<PolygonIterator> polygon_iterators;
+ std::vector<item_type> polygon_iterators;
signed_size_type multi_index = 0;
for (PolygonIterator it = polygons_first; it != polygons_beyond;
++it, ++multi_index)
{
if (multi_indices.find(multi_index) == multi_indices.end())
{
- polygon_iterators.push_back(it);
+ polygon_iterators.push_back(item_type(it));
}
}
- typename base::item_visitor_type item_visitor;
+ // prepare strategies
+ typedef typename std::iterator_traits<PolygonIterator>::value_type polygon_type;
+ typedef typename Strategy::template point_in_geometry_strategy
+ <
+ polygon_type, polygon_type
+ >::type within_strategy_type;
+ within_strategy_type const within_strategy
+ = strategy.template get_point_in_geometry_strategy<polygon_type, polygon_type>();
+ typedef typename Strategy::envelope_strategy_type envelope_strategy_type;
+ envelope_strategy_type const envelope_strategy
+ = strategy.get_envelope_strategy();
+
+ // call partition to check if polygons are disjoint from each other
+ typename base::template item_visitor_type<within_strategy_type> item_visitor(within_strategy);
geometry::partition
<
geometry::model::box<typename point_type<MultiPolygon>::type>
>::apply(polygon_iterators, item_visitor,
- typename base::expand_box(),
- typename base::overlaps_box());
+ typename base::template expand_box<envelope_strategy_type>(envelope_strategy),
+ typename base::template overlaps_box<envelope_strategy_type>(envelope_strategy));
if (item_visitor.items_overlap)
{
@@ -155,13 +176,15 @@ private:
<
typename PolygonIterator,
typename TurnIterator,
- typename VisitPolicy
+ typename VisitPolicy,
+ typename Strategy
>
static inline bool apply(PolygonIterator polygons_first,
PolygonIterator polygons_beyond,
TurnIterator turns_first,
TurnIterator turns_beyond,
- VisitPolicy& visitor)
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
signed_size_type multi_index = 0;
for (PolygonIterator it = polygons_first; it != polygons_beyond;
@@ -185,7 +208,8 @@ private:
if (! Predicate::apply(*it,
filtered_turns_first,
filtered_turns_beyond,
- visitor))
+ visitor,
+ strategy))
{
return false;
}
@@ -200,19 +224,21 @@ private:
<
typename PolygonIterator,
typename TurnIterator,
- typename VisitPolicy
+ typename VisitPolicy,
+ typename Strategy
>
static inline bool have_holes_inside(PolygonIterator polygons_first,
PolygonIterator polygons_beyond,
TurnIterator turns_first,
TurnIterator turns_beyond,
- VisitPolicy& visitor)
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
return has_property_per_polygon
<
typename base::has_holes_inside
>::apply(polygons_first, polygons_beyond,
- turns_first, turns_beyond, visitor);
+ turns_first, turns_beyond, visitor, strategy);
}
@@ -221,19 +247,21 @@ private:
<
typename PolygonIterator,
typename TurnIterator,
- typename VisitPolicy
+ typename VisitPolicy,
+ typename Strategy
>
static inline bool have_connected_interior(PolygonIterator polygons_first,
PolygonIterator polygons_beyond,
TurnIterator turns_first,
TurnIterator turns_beyond,
- VisitPolicy& visitor)
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
return has_property_per_polygon
<
typename base::has_connected_interior
>::apply(polygons_first, polygons_beyond,
- turns_first, turns_beyond, visitor);
+ turns_first, turns_beyond, visitor, strategy);
}
@@ -307,7 +335,8 @@ public:
boost::end(multipolygon),
turns.begin(),
turns.end(),
- visitor))
+ visitor,
+ strategy))
{
return false;
}
@@ -320,7 +349,8 @@ public:
boost::end(multipolygon),
turns.begin(),
turns.end(),
- visitor))
+ visitor,
+ strategy))
{
return false;
}
@@ -332,7 +362,8 @@ public:
boost::end(multipolygon),
turns.begin(),
turns.end(),
- visitor);
+ visitor,
+ strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/is_valid/polygon.hpp b/boost/geometry/algorithms/detail/is_valid/polygon.hpp
index f7e22fb8d2..5c6229b793 100644
--- a/boost/geometry/algorithms/detail/is_valid/polygon.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/polygon.hpp
@@ -1,5 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
+// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
+
// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -43,6 +45,7 @@
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/algorithms/num_interior_rings.hpp>
#include <boost/geometry/algorithms/validity_failure_type.hpp>
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
@@ -142,43 +145,103 @@ protected:
};
+ // Iterator value_type is a Ring or Polygon
+ template <typename Iterator, typename Box>
+ struct partition_item
+ {
+ explicit partition_item(Iterator it)
+ : m_it(it)
+ , m_is_initialized(false)
+ {}
+
+ Iterator get() const
+ {
+ return m_it;
+ }
+
+ template <typename EnvelopeStrategy>
+ Box const& get_envelope(EnvelopeStrategy const& strategy) const
+ {
+ if (! m_is_initialized)
+ {
+ m_box = geometry::return_envelope<Box>(*m_it, strategy);
+ m_is_initialized = true;
+ }
+ return m_box;
+ }
+
+ private:
+ Iterator m_it;
+ mutable Box m_box;
+ mutable bool m_is_initialized;
+ };
+
// structs for partition -- start
+ template <typename EnvelopeStrategy>
struct expand_box
{
+ explicit expand_box(EnvelopeStrategy const& strategy) : m_strategy(strategy) {}
+
template <typename Box, typename Iterator>
- static inline void apply(Box& total, Iterator const& it)
+ inline void apply(Box& total, partition_item<Iterator, Box> const& item) const
{
- geometry::expand(total, geometry::return_envelope<Box>(*it));
+ geometry::expand(total, item.get_envelope(m_strategy));
}
+ EnvelopeStrategy const& m_strategy;
};
+ template <typename EnvelopeStrategy>
struct overlaps_box
{
+ explicit overlaps_box(EnvelopeStrategy const& strategy) : m_strategy(strategy) {}
+
template <typename Box, typename Iterator>
- static inline bool apply(Box const& box, Iterator const& it)
+ inline bool apply(Box const& box, partition_item<Iterator, Box> const& item) const
{
- return ! geometry::disjoint(*it, box);
+ return ! geometry::disjoint(item.get_envelope(m_strategy), box);
}
+
+ EnvelopeStrategy const& m_strategy;
};
+ template <typename WithinStrategy>
struct item_visitor_type
{
bool items_overlap;
+ WithinStrategy const& m_strategy;
+
+ explicit item_visitor_type(WithinStrategy const& strategy)
+ : items_overlap(false)
+ , m_strategy(strategy)
+ {}
- item_visitor_type() : items_overlap(false) {}
+ template <typename Item>
+ inline bool is_within(Item const& first, Item const& second)
+ {
+ typename point_type<Polygon>::type point;
+ typedef detail::point_on_border::point_on_range<true> pob;
+
+ // TODO: this should check for a point on the interior, instead
+ // of on border. Or it should check using the overlap function.
+
+ return pob::apply(point, points_begin(first), points_end(first))
+ && geometry::within(point, second, m_strategy);
+ }
- template <typename Item1, typename Item2>
- inline void apply(Item1 const& item1, Item2 const& item2)
+ template <typename Iterator, typename Box>
+ inline bool apply(partition_item<Iterator, Box> const& item1,
+ partition_item<Iterator, Box> const& item2)
{
if (! items_overlap
- && (geometry::within(*points_begin(*item1), *item2)
- || geometry::within(*points_begin(*item2), *item1))
- )
+ && (is_within(*item1.get(), *item2.get())
+ || is_within(*item2.get(), *item1.get())))
{
items_overlap = true;
+ return false; // interrupt
}
+ return true;
}
};
// structs for partition -- end
@@ -189,14 +252,16 @@ protected:
typename RingIterator,
typename ExteriorRing,
typename TurnIterator,
- typename VisitPolicy
+ typename VisitPolicy,
+ typename Strategy
>
static inline bool are_holes_inside(RingIterator rings_first,
RingIterator rings_beyond,
ExteriorRing const& exterior_ring,
TurnIterator turns_first,
TurnIterator turns_beyond,
- VisitPolicy& visitor)
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
boost::ignore_unused(visitor);
@@ -217,6 +282,14 @@ protected:
}
}
+ // prepare strategy
+ typedef typename std::iterator_traits<RingIterator>::value_type inter_ring_type;
+ typename Strategy::template point_in_geometry_strategy
+ <
+ inter_ring_type, ExteriorRing
+ >::type const in_exterior_strategy
+ = strategy.template get_point_in_geometry_strategy<inter_ring_type, ExteriorRing>();
+
signed_size_type ring_index = 0;
for (RingIterator it = rings_first; it != rings_beyond;
++it, ++ring_index)
@@ -224,7 +297,7 @@ protected:
// do not examine interior rings that have turns with the
// exterior ring
if (ring_indices.find(ring_index) == ring_indices.end()
- && ! geometry::covered_by(range::front(*it), exterior_ring))
+ && ! geometry::covered_by(range::front(*it), exterior_ring, in_exterior_strategy))
{
return visitor.template apply<failure_interior_rings_outside>();
}
@@ -237,26 +310,42 @@ protected:
ring_indices.insert(tit->operations[1].seg_id.ring_index);
}
+ typedef geometry::model::box<typename point_type<Polygon>::type> box_type;
+ typedef partition_item<RingIterator, box_type> item_type;
+
// put iterators for interior rings without turns in a vector
- std::vector<RingIterator> ring_iterators;
+ std::vector<item_type> ring_iterators;
ring_index = 0;
for (RingIterator it = rings_first; it != rings_beyond;
++it, ++ring_index)
{
if (ring_indices.find(ring_index) == ring_indices.end())
{
- ring_iterators.push_back(it);
+ ring_iterators.push_back(item_type(it));
}
}
- // call partition to check is interior rings are disjoint from
+ // prepare strategies
+ typedef typename Strategy::template point_in_geometry_strategy
+ <
+ inter_ring_type, inter_ring_type
+ >::type in_interior_strategy_type;
+ in_interior_strategy_type const in_interior_strategy
+ = strategy.template get_point_in_geometry_strategy<inter_ring_type, inter_ring_type>();
+ typedef typename Strategy::envelope_strategy_type envelope_strategy_type;
+ envelope_strategy_type const envelope_strategy
+ = strategy.get_envelope_strategy();
+
+ // call partition to check if interior rings are disjoint from
// each other
- item_visitor_type item_visitor;
+ item_visitor_type<in_interior_strategy_type> item_visitor(in_interior_strategy);
geometry::partition
<
- geometry::model::box<typename point_type<Polygon>::type>
- >::apply(ring_iterators, item_visitor, expand_box(), overlaps_box());
+ box_type
+ >::apply(ring_iterators, item_visitor,
+ expand_box<envelope_strategy_type>(envelope_strategy),
+ overlaps_box<envelope_strategy_type>(envelope_strategy));
if (item_visitor.items_overlap)
{
@@ -273,35 +362,40 @@ protected:
typename InteriorRings,
typename ExteriorRing,
typename TurnIterator,
- typename VisitPolicy
+ typename VisitPolicy,
+ typename Strategy
>
static inline bool are_holes_inside(InteriorRings const& interior_rings,
ExteriorRing const& exterior_ring,
TurnIterator first,
TurnIterator beyond,
- VisitPolicy& visitor)
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
return are_holes_inside(boost::begin(interior_rings),
boost::end(interior_rings),
exterior_ring,
first,
beyond,
- visitor);
+ visitor,
+ strategy);
}
struct has_holes_inside
{
- template <typename TurnIterator, typename VisitPolicy>
+ template <typename TurnIterator, typename VisitPolicy, typename Strategy>
static inline bool apply(Polygon const& polygon,
TurnIterator first,
TurnIterator beyond,
- VisitPolicy& visitor)
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
return are_holes_inside(geometry::interior_rings(polygon),
geometry::exterior_ring(polygon),
first,
beyond,
- visitor);
+ visitor,
+ strategy);
}
};
@@ -310,11 +404,12 @@ protected:
struct has_connected_interior
{
- template <typename TurnIterator, typename VisitPolicy>
+ template <typename TurnIterator, typename VisitPolicy, typename Strategy>
static inline bool apply(Polygon const& polygon,
TurnIterator first,
TurnIterator beyond,
- VisitPolicy& visitor)
+ VisitPolicy& visitor,
+ Strategy const& )
{
boost::ignore_unused(visitor);
@@ -388,7 +483,8 @@ public:
if (! has_holes_inside::apply(polygon,
turns.begin(), turns.end(),
- visitor))
+ visitor,
+ strategy))
{
return false;
}
@@ -399,7 +495,8 @@ public:
return has_connected_interior::apply(polygon,
turns.begin(),
turns.end(),
- visitor);
+ visitor,
+ strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/is_valid/ring.hpp b/boost/geometry/algorithms/detail/is_valid/ring.hpp
index 9ab68fdc48..0b95950430 100644
--- a/boost/geometry/algorithms/detail/is_valid/ring.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/ring.hpp
@@ -115,7 +115,10 @@ struct is_properly_oriented
geometry::closure<Ring>::value
> ring_area_type;
- typedef typename default_area_result<Ring>::type area_result_type;
+ typedef typename Strategy::template area_strategy
+ <
+ point_type
+ >::type::return_type area_result_type;
typename ring_area_predicate
<
@@ -195,7 +198,7 @@ struct is_valid_ring
return
is_topologically_closed<Ring, closure>::apply(ring, visitor)
&& ! has_duplicates<Ring, closure>::apply(ring, visitor)
- && ! has_spikes<Ring, closure>::apply(ring, visitor)
+ && ! has_spikes<Ring, closure>::apply(ring, visitor, strategy.get_side_strategy())
&& (! CheckSelfIntersections
|| has_valid_self_turns<Ring>::apply(ring, visitor, strategy))
&& is_properly_oriented<Ring, IsInteriorRing>::apply(ring, visitor, strategy);
diff --git a/boost/geometry/algorithms/detail/multi_modify.hpp b/boost/geometry/algorithms/detail/multi_modify.hpp
index f0b9ddd3e6..23187f9323 100644
--- a/boost/geometry/algorithms/detail/multi_modify.hpp
+++ b/boost/geometry/algorithms/detail/multi_modify.hpp
@@ -4,6 +4,10 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -40,6 +44,18 @@ struct multi_modify
Policy::apply(*it);
}
}
+
+ template <typename Strategy>
+ static inline void apply(MultiGeometry& multi, Strategy const& strategy)
+ {
+ typedef typename boost::range_iterator<MultiGeometry>::type iterator_type;
+ for (iterator_type it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ Policy::apply(*it, strategy);
+ }
+ }
};
diff --git a/boost/geometry/algorithms/detail/occupation_info.hpp b/boost/geometry/algorithms/detail/occupation_info.hpp
index 4048d59d75..fc74f0cc7f 100644
--- a/boost/geometry/algorithms/detail/occupation_info.hpp
+++ b/boost/geometry/algorithms/detail/occupation_info.hpp
@@ -2,6 +2,11 @@
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -99,12 +104,18 @@ public :
}
}
- template <typename RobustPoint, typename Turns>
- inline void get_left_turns(RobustPoint const& origin, Turns& turns)
+ template <typename RobustPoint, typename Turns, typename SideStrategy>
+ inline void get_left_turns(RobustPoint const& origin, Turns& turns,
+ SideStrategy const& strategy)
{
+ typedef detail::left_turns::angle_less
+ <
+ typename AngleInfo::point_type,
+ SideStrategy
+ > angle_less;
+
// Sort on angle
- std::sort(m_angles.begin(), m_angles.end(),
- detail::left_turns::angle_less<typename AngleInfo::point_type>(origin));
+ std::sort(m_angles.begin(), m_angles.end(), angle_less(origin, strategy));
// Group same-angled elements
std::size_t cluster_size = detail::left_turns::assign_cluster_indices(m_angles, origin);
diff --git a/boost/geometry/algorithms/detail/overlaps/implementation.hpp b/boost/geometry/algorithms/detail/overlaps/implementation.hpp
new file mode 100644
index 0000000000..49f44bef81
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlaps/implementation.hpp
@@ -0,0 +1,156 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
+
+// This file was modified by Oracle on 2014, 2015, 2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the 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_GEOMETRY_ALGORITHMS_DETAIL_OVERLAPS_IMPLEMENTATION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAPS_IMPLEMENTATION_HPP
+
+
+#include <cstddef>
+
+#include <boost/geometry/core/access.hpp>
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/relate.hpp>
+#include <boost/geometry/algorithms/detail/overlaps/interface.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlaps
+{
+
+template
+<
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct box_box_loop
+{
+ template <typename Box1, typename Box2>
+ static inline void apply(Box1 const& b1, Box2 const& b2,
+ bool& overlaps, bool& one_in_two, bool& two_in_one)
+ {
+ assert_dimension_equal<Box1, Box2>();
+
+ typedef typename coordinate_type<Box1>::type coordinate_type1;
+ typedef typename coordinate_type<Box2>::type coordinate_type2;
+
+ coordinate_type1 const& min1 = get<min_corner, Dimension>(b1);
+ coordinate_type1 const& max1 = get<max_corner, Dimension>(b1);
+ coordinate_type2 const& min2 = get<min_corner, Dimension>(b2);
+ coordinate_type2 const& max2 = get<max_corner, Dimension>(b2);
+
+ // We might use the (not yet accepted) Boost.Interval
+ // submission in the future
+
+ // If:
+ // B1: |-------|
+ // B2: |------|
+ // in any dimension -> no overlap
+ if (max1 <= min2 || min1 >= max2)
+ {
+ overlaps = false;
+ return;
+ }
+
+ // If:
+ // B1: |--------------------|
+ // B2: |-------------|
+ // in all dimensions -> within, then no overlap
+ // B1: |--------------------|
+ // B2: |-------------|
+ // this is "within-touch" -> then no overlap. So use < and >
+ if (min1 < min2 || max1 > max2)
+ {
+ one_in_two = false;
+ }
+
+ // Same other way round
+ if (min2 < min1 || max2 > max1)
+ {
+ two_in_one = false;
+ }
+
+ box_box_loop
+ <
+ Dimension + 1,
+ DimensionCount
+ >::apply(b1, b2, overlaps, one_in_two, two_in_one);
+ }
+};
+
+template
+<
+ std::size_t DimensionCount
+>
+struct box_box_loop<DimensionCount, DimensionCount>
+{
+ template <typename Box1, typename Box2>
+ static inline void apply(Box1 const& , Box2 const&, bool&, bool&, bool&)
+ {
+ }
+};
+
+struct box_box
+{
+ template <typename Box1, typename Box2, typename Strategy>
+ static inline bool apply(Box1 const& b1, Box2 const& b2, Strategy const& /*strategy*/)
+ {
+ bool overlaps = true;
+ bool within1 = true;
+ bool within2 = true;
+ box_box_loop
+ <
+ 0,
+ dimension<Box1>::type::value
+ >::apply(b1, b2, overlaps, within1, within2);
+
+ /*
+ \see http://docs.codehaus.org/display/GEOTDOC/02+Geometry+Relationships#02GeometryRelationships-Overlaps
+ where is stated that "inside" is not an "overlap",
+ this is true and is implemented as such.
+ */
+ return overlaps && ! within1 && ! within2;
+ }
+};
+
+}} // namespace detail::overlaps
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Box1, typename Box2>
+struct overlaps<Box1, Box2, box_tag, box_tag>
+ : detail::overlaps::box_box
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAPS_IMPLEMENTATION_HPP
diff --git a/boost/geometry/algorithms/detail/overlaps/interface.hpp b/boost/geometry/algorithms/detail/overlaps/interface.hpp
new file mode 100644
index 0000000000..f9f6a853fd
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlaps/interface.hpp
@@ -0,0 +1,124 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
+
+// This file was modified by Oracle on 2014, 2015, 2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the 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_GEOMETRY_ALGORITHMS_DETAIL_OVERLAPS_INTERFACE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAPS_INTERFACE_HPP
+
+
+#include <cstddef>
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
+
+#include <boost/geometry/strategies/relate.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Tag1 = typename tag<Geometry1>::type,
+ typename Tag2 = typename tag<Geometry2>::type
+>
+struct overlaps
+ : detail::relate::relate_impl
+ <
+ detail::de9im::static_mask_overlaps_type,
+ Geometry1,
+ Geometry2
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief \brief_check2{overlap}
+\ingroup overlaps
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Strategy \tparam_strategy{Overlaps}
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param strategy \param_strategy{overlaps}
+\return \return_check2{overlap}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/overlaps.qbk]}
+*/
+template <typename Geometry1, typename Geometry2, typename Strategy>
+inline bool overlaps(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ concepts::check<Geometry1 const>();
+ concepts::check<Geometry2 const>();
+
+ return dispatch::overlaps
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy);
+}
+
+/*!
+\brief \brief_check2{overlap}
+\ingroup overlaps
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\return \return_check2{overlap}
+
+\qbk{[include reference/algorithms/overlaps.qbk]}
+*/
+template <typename Geometry1, typename Geometry2>
+inline bool overlaps(Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ concepts::check<Geometry1 const>();
+ concepts::check<Geometry2 const>();
+
+ typedef typename strategy::relate::services::default_strategy
+ <
+ Geometry1,
+ Geometry2
+ >::type strategy_type;
+
+ return dispatch::overlaps
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy_type());
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAPS_INTERFACE_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/aggregate_operations.hpp b/boost/geometry/algorithms/detail/overlay/aggregate_operations.hpp
index df62a1f2f6..106ecaad07 100644
--- a/boost/geometry/algorithms/detail/overlay/aggregate_operations.hpp
+++ b/boost/geometry/algorithms/detail/overlay/aggregate_operations.hpp
@@ -24,8 +24,12 @@ struct ring_with_direction
{
ring_identifier ring_id;
direction_type direction;
- bool only_turn_on_ring;
+ std::size_t turn_index;
+ int operation_index;
+ operation_type operation;
+ signed_size_type region_id;
+ bool isolated;
inline bool operator<(ring_with_direction const& other) const
{
@@ -36,7 +40,11 @@ struct ring_with_direction
ring_with_direction()
: direction(dir_unknown)
- , only_turn_on_ring(false)
+ , turn_index(-1)
+ , operation_index(0)
+ , operation(operation_none)
+ , region_id(-1)
+ , isolated(false)
{}
};
@@ -50,28 +58,168 @@ struct rank_with_rings
{
}
+ inline bool all_equal(direction_type dir_type) const
+ {
+ for (std::set<ring_with_direction>::const_iterator it = rings.begin();
+ it != rings.end(); ++it)
+ {
+ if (it->direction != dir_type)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
inline bool all_to() const
{
+ return all_equal(sort_by_side::dir_to);
+ }
+
+ inline bool all_from() const
+ {
+ return all_equal(sort_by_side::dir_from);
+ }
+
+ inline bool has_only(operation_type op) const
+ {
+ for (std::set<ring_with_direction>::const_iterator it = rings.begin();
+ it != rings.end(); ++it)
+ {
+ const ring_with_direction& rwd = *it;
+ if (rwd.operation != op)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ //! Check if set has both op1 and op2, but no others
+ inline bool has_only_both(operation_type op1, operation_type op2) const
+ {
+ bool has1 = false;
+ bool has2 = false;
for (std::set<ring_with_direction>::const_iterator it = rings.begin();
it != rings.end(); ++it)
{
- if (it->direction == sort_by_side::dir_from)
+ const ring_with_direction& rwd = *it;
+
+ if (rwd.operation == op1) { has1 = true; }
+ else if (rwd.operation == op2) { has2 = true; }
+ else { return false; }
+ }
+ return has1 && has2;
+ }
+
+ inline bool is_isolated() const
+ {
+ for (std::set<ring_with_direction>::const_iterator it = rings.begin();
+ it != rings.end(); ++it)
+ {
+ const ring_with_direction& rwd = *it;
+ if (! rwd.isolated)
{
return false;
}
}
return true;
}
+
+ inline bool has_unique_region_id() const
+ {
+ int region_id = -1;
+ for (std::set<ring_with_direction>::const_iterator it = rings.begin();
+ it != rings.end(); ++it)
+ {
+ const ring_with_direction& rwd = *it;
+ if (region_id == -1)
+ {
+ region_id = rwd.region_id;
+ }
+ else if (rwd.region_id != region_id)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ inline int region_id() const
+ {
+ int region_id = -1;
+ for (std::set<ring_with_direction>::const_iterator it = rings.begin();
+ it != rings.end(); ++it)
+ {
+ const ring_with_direction& rwd = *it;
+ if (region_id == -1)
+ {
+ region_id = rwd.region_id;
+ }
+ else if (rwd.region_id != region_id)
+ {
+ return -1;
+ }
+ }
+ return region_id;
+ }
+
+ template <typename Turns>
+ inline bool traversable(Turns const& turns) const
+ {
+ typedef typename boost::range_value<Turns>::type turn_type;
+ typedef typename turn_type::turn_operation_type turn_operation_type;
+
+ for (std::set<ring_with_direction>::const_iterator it = rings.begin();
+ it != rings.end(); ++it)
+ {
+ const ring_with_direction& rwd = *it;
+ turn_type const& turn = turns[rwd.turn_index];
+ turn_operation_type const& op = turn.operations[rwd.operation_index];
+
+ // TODO: this is still necessary, but makes it order-dependent
+ // which should not be done.
+
+ // This would obsolete the whole function and should be solved
+ // in a different way
+ if (op.visited.finalized() || op.visited.visited())
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
};
-template <typename Sbs>
-inline void aggregate_operations(Sbs const& sbs, std::vector<rank_with_rings>& aggregation)
+template <typename Sbs, typename Turns>
+inline void aggregate_operations(Sbs const& sbs, std::vector<rank_with_rings>& aggregation,
+ Turns const& turns,
+ operation_type target_operation)
{
+ typedef typename boost::range_value<Turns>::type turn_type;
+ typedef typename turn_type::turn_operation_type turn_operation_type;
+
aggregation.clear();
for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
{
typename Sbs::rp const& ranked_point = sbs.m_ranked_points[i];
+ turn_type const& turn = turns[ranked_point.turn_index];
+
+ turn_operation_type const& op = turn.operations[ranked_point.operation_index];
+
+ if (! ((target_operation == operation_union && ranked_point.rank == 0)
+ || op.operation == target_operation
+ || op.operation == operation_continue
+ || (op.operation == operation_blocked && ranked_point.direction == dir_from)))
+ {
+ // Always take rank 0 (because self-turns are blocked)
+ // Don't consider union/blocked (aggregate is only used for intersections)
+ // Blocked is allowed for from
+ continue;
+ }
+
if (aggregation.empty() || aggregation.back().rank != ranked_point.rank)
{
rank_with_rings current;
@@ -81,10 +229,14 @@ inline void aggregate_operations(Sbs const& sbs, std::vector<rank_with_rings>& a
ring_with_direction rwd;
segment_identifier const& sid = ranked_point.seg_id;
+
rwd.ring_id = ring_identifier(sid.source_index, sid.multi_index, sid.ring_index);
rwd.direction = ranked_point.direction;
- rwd.only_turn_on_ring = ranked_point.only_turn_on_ring;
-
+ rwd.turn_index = ranked_point.turn_index;
+ rwd.operation_index = ranked_point.operation_index;
+ rwd.operation = op.operation;
+ rwd.region_id = op.enriched.region_id;
+ rwd.isolated = op.enriched.isolated;
aggregation.back().rings.insert(rwd);
}
diff --git a/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp b/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp
index 03c06c28d1..fb73840798 100644
--- a/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp
+++ b/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014.
-// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -63,8 +63,9 @@ inline bool points_equal_or_close(Point1 const& point1,
}
-template <typename Range, typename Point, typename RobustPolicy>
+template <typename Range, typename Point, typename SideStrategy, typename RobustPolicy>
inline void append_no_dups_or_spikes(Range& range, Point const& point,
+ SideStrategy const& strategy,
RobustPolicy const& robust_policy)
{
#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
@@ -92,6 +93,7 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point,
&& point_is_spike_or_equal(point,
*(boost::end(range) - 3),
*(boost::end(range) - 2),
+ strategy,
robust_policy))
{
// Use the Concept/traits, so resize and append again
@@ -100,8 +102,9 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point,
}
}
-template <typename Range, typename RobustPolicy>
+template <typename Range, typename SideStrategy, typename RobustPolicy>
inline void clean_closing_dups_and_spikes(Range& range,
+ SideStrategy const& strategy,
RobustPolicy const& robust_policy)
{
std::size_t const minsize
@@ -135,7 +138,7 @@ inline void clean_closing_dups_and_spikes(Range& range,
// Check if closing point is a spike (this is so if the second point is
// considered as a spike w.r.t. the last segment)
- if (point_is_spike_or_equal(*second, *ultimate, *first, robust_policy))
+ if (point_is_spike_or_equal(*second, *ultimate, *first, strategy, robust_policy))
{
range::erase(range, first);
if (BOOST_GEOMETRY_CONDITION(closed))
diff --git a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
index 2408b4b68e..78160f5204 100644
--- a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
+++ b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
@@ -20,7 +20,8 @@
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/algorithms/detail/partition.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
-#include <boost/geometry/algorithms/within.hpp>
+#include <boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp>
+#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/geometries/box.hpp>
@@ -37,50 +38,88 @@ namespace detail { namespace overlay
template
<
typename Item,
+ typename InnerGeometry,
typename Geometry1, typename Geometry2,
- typename RingCollection
+ typename RingCollection,
+ typename Strategy
+>
+static inline bool within_selected_input(Item const& item2,
+ InnerGeometry const& inner_geometry,
+ ring_identifier const& outer_id,
+ Geometry1 const& geometry1, Geometry2 const& geometry2,
+ RingCollection const& collection,
+ Strategy const& strategy)
+{
+ typedef typename geometry::tag<Geometry1>::type tag1;
+ typedef typename geometry::tag<Geometry2>::type tag2;
+
+ // NOTE: range_in_geometry first checks the item2.point and then
+ // if this point is on boundary it checks points of inner_geometry
+ // ring until a point inside/outside other geometry ring is found
+ switch (outer_id.source_index)
+ {
+ // covered_by
+ case 0 :
+ return range_in_geometry(item2.point, inner_geometry,
+ get_ring<tag1>::apply(outer_id, geometry1), strategy) >= 0;
+ case 1 :
+ return range_in_geometry(item2.point, inner_geometry,
+ get_ring<tag2>::apply(outer_id, geometry2), strategy) >= 0;
+ case 2 :
+ return range_in_geometry(item2.point, inner_geometry,
+ get_ring<void>::apply(outer_id, collection), strategy) >= 0;
+ }
+ return false;
+}
+
+template
+<
+ typename Item,
+ typename Geometry1, typename Geometry2,
+ typename RingCollection,
+ typename Strategy
>
-static inline bool within_selected_input(Item const& item2, ring_identifier const& ring_id,
+static inline bool within_selected_input(Item const& item2,
+ ring_identifier const& inner_id, ring_identifier const& outer_id,
Geometry1 const& geometry1, Geometry2 const& geometry2,
- RingCollection const& collection)
+ RingCollection const& collection,
+ Strategy const& strategy)
{
typedef typename geometry::tag<Geometry1>::type tag1;
typedef typename geometry::tag<Geometry2>::type tag2;
- switch (ring_id.source_index)
+ switch (inner_id.source_index)
{
case 0 :
- return geometry::within(item2.point,
- get_ring<tag1>::apply(ring_id, geometry1));
- break;
+ return within_selected_input(item2,
+ get_ring<tag1>::apply(inner_id, geometry1),
+ outer_id, geometry1, geometry2, collection, strategy);
case 1 :
- return geometry::within(item2.point,
- get_ring<tag2>::apply(ring_id, geometry2));
- break;
+ return within_selected_input(item2,
+ get_ring<tag2>::apply(inner_id, geometry2),
+ outer_id, geometry1, geometry2, collection, strategy);
case 2 :
- return geometry::within(item2.point,
- get_ring<void>::apply(ring_id, collection));
- break;
+ return within_selected_input(item2,
+ get_ring<void>::apply(inner_id, collection),
+ outer_id, geometry1, geometry2, collection, strategy);
}
return false;
}
-template <typename Point>
+template <typename Point, typename AreaType>
struct ring_info_helper
{
- typedef typename geometry::default_area_result<Point>::type area_type;
-
ring_identifier id;
- area_type real_area;
- area_type abs_area;
+ AreaType real_area;
+ AreaType abs_area;
model::box<Point> envelope;
inline ring_info_helper()
: real_area(0), abs_area(0)
{}
- inline ring_info_helper(ring_identifier i, area_type a)
+ inline ring_info_helper(ring_identifier i, AreaType const& a)
: id(i), real_area(a), abs_area(geometry::math::abs(a))
{}
};
@@ -104,7 +143,14 @@ struct ring_info_helper_ovelaps_box
}
};
-template <typename Geometry1, typename Geometry2, typename Collection, typename RingMap>
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Collection,
+ typename RingMap,
+ typename Strategy
+>
struct assign_visitor
{
typedef typename RingMap::mapped_type ring_info_type;
@@ -113,26 +159,27 @@ struct assign_visitor
Geometry2 const& m_geometry2;
Collection const& m_collection;
RingMap& m_ring_map;
+ Strategy const& m_strategy;
bool m_check_for_orientation;
-
inline assign_visitor(Geometry1 const& g1, Geometry2 const& g2, Collection const& c,
- RingMap& map, bool check)
+ RingMap& map, Strategy const& strategy, bool check)
: m_geometry1(g1)
, m_geometry2(g2)
, m_collection(c)
, m_ring_map(map)
+ , m_strategy(strategy)
, m_check_for_orientation(check)
{}
template <typename Item>
- inline void apply(Item const& outer, Item const& inner, bool first = true)
+ inline bool apply(Item const& outer, Item const& inner, bool first = true)
{
if (first && outer.abs_area < inner.abs_area)
{
// Apply with reversed arguments
apply(inner, outer, false);
- return;
+ return true;
}
if (m_check_for_orientation
@@ -141,8 +188,10 @@ struct assign_visitor
{
ring_info_type& inner_in_map = m_ring_map[inner.id];
- if (geometry::within(inner_in_map.point, outer.envelope)
- && within_selected_input(inner_in_map, outer.id, m_geometry1, m_geometry2, m_collection)
+ if (geometry::covered_by(inner_in_map.point, outer.envelope)
+ && within_selected_input(inner_in_map, inner.id, outer.id,
+ m_geometry1, m_geometry2, m_collection,
+ m_strategy)
)
{
// Assign a parent if there was no earlier parent, or the newly
@@ -155,6 +204,8 @@ struct assign_visitor
}
}
}
+
+ return true;
}
};
@@ -165,12 +216,14 @@ template
<
typename Geometry1, typename Geometry2,
typename RingCollection,
- typename RingMap
+ typename RingMap,
+ typename Strategy
>
inline void assign_parents(Geometry1 const& geometry1,
Geometry2 const& geometry2,
RingCollection const& collection,
RingMap& ring_map,
+ Strategy const& strategy,
bool check_for_orientation = false)
{
typedef typename geometry::tag<Geometry1>::type tag1;
@@ -179,11 +232,15 @@ inline void assign_parents(Geometry1 const& geometry1,
typedef typename RingMap::mapped_type ring_info_type;
typedef typename ring_info_type::point_type point_type;
typedef model::box<point_type> box_type;
+ typedef typename Strategy::template area_strategy
+ <
+ point_type
+ >::type::return_type area_result_type;
typedef typename RingMap::iterator map_iterator_type;
{
- typedef ring_info_helper<point_type> helper;
+ typedef ring_info_helper<point_type, area_result_type> helper;
typedef std::vector<helper> vector_type;
typedef typename boost::range_iterator<vector_type const>::type vector_iterator_type;
@@ -204,17 +261,21 @@ inline void assign_parents(Geometry1 const& geometry1,
{
case 0 :
geometry::envelope(get_ring<tag1>::apply(it->first, geometry1),
- item.envelope);
+ item.envelope, strategy.get_envelope_strategy());
break;
case 1 :
geometry::envelope(get_ring<tag2>::apply(it->first, geometry2),
- item.envelope);
+ item.envelope, strategy.get_envelope_strategy());
break;
case 2 :
geometry::envelope(get_ring<void>::apply(it->first, collection),
- item.envelope);
+ item.envelope, strategy.get_envelope_strategy());
break;
}
+
+ // Expand envelope slightly
+ expand_by_epsilon(item.envelope);
+
if (item.real_area > 0)
{
count_positive++;
@@ -257,8 +318,9 @@ inline void assign_parents(Geometry1 const& geometry1,
assign_visitor
<
Geometry1, Geometry2,
- RingCollection, RingMap
- > visitor(geometry1, geometry2, collection, ring_map, check_for_orientation);
+ RingCollection, RingMap,
+ Strategy
+ > visitor(geometry1, geometry2, collection, ring_map, strategy, check_for_orientation);
geometry::partition
<
@@ -315,18 +377,20 @@ template
<
typename Geometry,
typename RingCollection,
- typename RingMap
+ typename RingMap,
+ typename Strategy
>
inline void assign_parents(Geometry const& geometry,
RingCollection const& collection,
RingMap& ring_map,
+ Strategy const& strategy,
bool check_for_orientation)
{
// Call it with an empty geometry as second geometry (source_id == 1)
// (ring_map should be empty for source_id==1)
Geometry empty;
- assign_parents(geometry, empty, collection, ring_map, check_for_orientation);
+ assign_parents(geometry, empty, collection, ring_map, strategy, check_for_orientation);
}
diff --git a/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp b/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp
index 795523d7a0..0e9bfe2ea0 100644
--- a/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp
+++ b/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp
@@ -20,6 +20,7 @@
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/convert.hpp>
+#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/iterators/ever_circling_iterator.hpp>
diff --git a/boost/geometry/algorithms/detail/overlay/copy_segments.hpp b/boost/geometry/algorithms/detail/overlay/copy_segments.hpp
index fe1a034f8b..c6f540a978 100644
--- a/boost/geometry/algorithms/detail/overlay/copy_segments.hpp
+++ b/boost/geometry/algorithms/detail/overlay/copy_segments.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014.
-// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -36,6 +36,7 @@
#include <boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp>
#include <boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp>
+#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
#include <boost/geometry/util/range.hpp>
@@ -56,12 +57,14 @@ struct copy_segments_ring
<
typename Ring,
typename SegmentIdentifier,
+ typename SideStrategy,
typename RobustPolicy,
typename RangeOut
>
static inline void apply(Ring const& ring,
SegmentIdentifier const& seg_id,
signed_size_type to_index,
+ SideStrategy const& strategy,
RobustPolicy const& robust_policy,
RangeOut& current_output)
{
@@ -108,7 +111,7 @@ struct copy_segments_ring
for (signed_size_type i = 0; i < count; ++i, ++it)
{
- detail::overlay::append_no_dups_or_spikes(current_output, *it, robust_policy);
+ detail::overlay::append_no_dups_or_spikes(current_output, *it, strategy, robust_policy);
}
}
};
@@ -118,20 +121,23 @@ class copy_segments_linestring
{
private:
// remove spikes
- template <typename RangeOut, typename Point, typename RobustPolicy>
+ template <typename RangeOut, typename Point, typename SideStrategy, typename RobustPolicy>
static inline void append_to_output(RangeOut& current_output,
Point const& point,
+ SideStrategy const& strategy,
RobustPolicy const& robust_policy,
boost::true_type const&)
{
detail::overlay::append_no_dups_or_spikes(current_output, point,
+ strategy,
robust_policy);
}
// keep spikes
- template <typename RangeOut, typename Point, typename RobustPolicy>
+ template <typename RangeOut, typename Point, typename SideStrategy, typename RobustPolicy>
static inline void append_to_output(RangeOut& current_output,
Point const& point,
+ SideStrategy const&,
RobustPolicy const&,
boost::false_type const&)
{
@@ -143,12 +149,14 @@ public:
<
typename LineString,
typename SegmentIdentifier,
+ typename SideStrategy,
typename RobustPolicy,
typename RangeOut
>
static inline void apply(LineString const& ls,
SegmentIdentifier const& seg_id,
signed_size_type to_index,
+ SideStrategy const& strategy,
RobustPolicy const& robust_policy,
RangeOut& current_output)
{
@@ -169,7 +177,7 @@ public:
for (signed_size_type i = 0; i < count; ++i, ++it)
{
- append_to_output(current_output, *it, robust_policy,
+ append_to_output(current_output, *it, strategy, robust_policy,
boost::integral_constant<bool, RemoveSpikes>());
}
}
@@ -182,12 +190,14 @@ struct copy_segments_polygon
<
typename Polygon,
typename SegmentIdentifier,
+ typename SideStrategy,
typename RobustPolicy,
typename RangeOut
>
static inline void apply(Polygon const& polygon,
SegmentIdentifier const& seg_id,
signed_size_type to_index,
+ SideStrategy const& strategy,
RobustPolicy const& robust_policy,
RangeOut& current_output)
{
@@ -198,6 +208,7 @@ struct copy_segments_polygon
? geometry::exterior_ring(polygon)
: range::at(geometry::interior_rings(polygon), seg_id.ring_index),
seg_id, to_index,
+ strategy,
robust_policy,
current_output
);
@@ -212,12 +223,14 @@ struct copy_segments_box
<
typename Box,
typename SegmentIdentifier,
+ typename SideStrategy,
typename RobustPolicy,
typename RangeOut
>
static inline void apply(Box const& box,
SegmentIdentifier const& seg_id,
signed_size_type to_index,
+ SideStrategy const& strategy,
RobustPolicy const& robust_policy,
RangeOut& current_output)
{
@@ -238,7 +251,7 @@ struct copy_segments_box
for (signed_size_type i = 0; i < count; i++, index++)
{
detail::overlay::append_no_dups_or_spikes(current_output,
- bp[index % 5], robust_policy);
+ bp[index % 5], strategy, robust_policy);
}
}
@@ -252,12 +265,14 @@ struct copy_segments_multi
<
typename MultiGeometry,
typename SegmentIdentifier,
+ typename SideStrategy,
typename RobustPolicy,
typename RangeOut
>
static inline void apply(MultiGeometry const& multi_geometry,
SegmentIdentifier const& seg_id,
signed_size_type to_index,
+ SideStrategy const& strategy,
RobustPolicy const& robust_policy,
RangeOut& current_output)
{
@@ -271,6 +286,7 @@ struct copy_segments_multi
// Call the single-version
Policy::apply(range::at(multi_geometry, seg_id.multi_index),
seg_id, to_index,
+ strategy,
robust_policy,
current_output);
}
@@ -340,12 +356,14 @@ template
bool Reverse,
typename Geometry,
typename SegmentIdentifier,
+ typename SideStrategy,
typename RobustPolicy,
typename RangeOut
>
inline void copy_segments(Geometry const& geometry,
SegmentIdentifier const& seg_id,
signed_size_type to_index,
+ SideStrategy const& strategy,
RobustPolicy const& robust_policy,
RangeOut& range_out)
{
@@ -355,7 +373,7 @@ inline void copy_segments(Geometry const& geometry,
<
typename tag<Geometry>::type,
Reverse
- >::apply(geometry, seg_id, to_index, robust_policy, range_out);
+ >::apply(geometry, seg_id, to_index, strategy, robust_policy, range_out);
}
diff --git a/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp b/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
index 5cab2b4cb8..47225328df 100644
--- a/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
+++ b/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
@@ -2,6 +2,11 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -19,20 +24,21 @@
# include <iostream>
# include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
# include <boost/geometry/io/wkt/wkt.hpp>
-# define BOOST_GEOMETRY_DEBUG_IDENTIFIER
+# if ! defined(BOOST_GEOMETRY_DEBUG_IDENTIFIER)
+# define BOOST_GEOMETRY_DEBUG_IDENTIFIER
+ #endif
#endif
#include <boost/range.hpp>
-#include <boost/geometry/iterators/ever_circling_iterator.hpp>
#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
-#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>
#include <boost/geometry/algorithms/detail/overlay/handle_colocations.hpp>
+#include <boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp>
+#include <boost/geometry/algorithms/detail/overlay/is_self_turn.hpp>
#include <boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
-#include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>
#include <boost/geometry/policies/robustness/robust_type.hpp>
-#include <boost/geometry/strategies/side.hpp>
+
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
# include <boost/geometry/algorithms/detail/overlay/check_enrich.hpp>
#endif
@@ -58,7 +64,7 @@ template
typename Turns,
typename Geometry1, typename Geometry2,
typename RobustPolicy,
- typename Strategy
+ typename SideStrategy
>
inline void enrich_sort(Operations& operations,
Turns const& turns,
@@ -66,7 +72,7 @@ inline void enrich_sort(Operations& operations,
Geometry1 const& geometry1,
Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
- Strategy const& /*strategy*/)
+ SideStrategy const& strategy)
{
std::sort(boost::begin(operations),
boost::end(operations),
@@ -76,8 +82,9 @@ inline void enrich_sort(Operations& operations,
typename boost::range_value<Operations>::type,
Geometry1, Geometry2,
RobustPolicy,
+ SideStrategy,
Reverse1, Reverse2
- >(turns, for_operation, geometry1, geometry2, robust_policy));
+ >(turns, for_operation, geometry1, geometry2, robust_policy, strategy));
}
@@ -145,7 +152,7 @@ inline void enrich_assign(Operations& operations, Turns& turns)
it != boost::end(operations);
++it)
{
- op_type& op = turns[it->turn_index]
+ op_type const& op = turns[it->turn_index]
.operations[it->operation_index];
std::cout << it->turn_index
@@ -171,9 +178,7 @@ inline void enrich_assign(Operations& operations, Turns& turns)
template <typename Turns, typename MappedVector>
-inline void create_map(Turns const& turns,
- detail::overlay::operation_type for_operation,
- MappedVector& mapped_vector)
+inline void create_map(Turns const& turns, MappedVector& mapped_vector)
{
typedef typename boost::range_value<Turns>::type turn_type;
typedef typename turn_type::container_type container_type;
@@ -195,15 +200,6 @@ inline void create_map(Turns const& turns,
continue;
}
- if (for_operation == operation_intersection
- && turn.cluster_id == -1
- && turn.both(operation_union))
- {
- // Only include uu turns if part of cluster (to block potential paths),
- // otherwise they can block possibly viable paths
- continue;
- }
-
std::size_t op_index = 0;
for (typename boost::range_iterator<container_type const>::type
op_it = boost::begin(turn.operations);
@@ -225,6 +221,56 @@ inline void create_map(Turns const& turns,
}
}
+template <typename Point1, typename Point2>
+inline typename geometry::coordinate_type<Point1>::type
+ distance_measure(Point1 const& a, Point2 const& b)
+{
+ // TODO: use comparable distance for point-point instead - but that
+ // causes currently cycling include problems
+ typedef typename geometry::coordinate_type<Point1>::type ctype;
+ ctype const dx = get<0>(a) - get<0>(b);
+ ctype const dy = get<1>(a) - get<1>(b);
+ return dx * dx + dy * dy;
+}
+
+template <typename Turns>
+inline void calculate_remaining_distance(Turns& turns)
+{
+ typedef typename boost::range_value<Turns>::type turn_type;
+ typedef typename turn_type::turn_operation_type op_type;
+
+ for (typename boost::range_iterator<Turns>::type
+ it = boost::begin(turns);
+ it != boost::end(turns);
+ ++it)
+ {
+ turn_type& turn = *it;
+ if (! turn.both(detail::overlay::operation_continue))
+ {
+ continue;
+ }
+
+ op_type& op0 = turn.operations[0];
+ op_type& op1 = turn.operations[1];
+
+ if (op0.remaining_distance != 0
+ || op1.remaining_distance != 0)
+ {
+ continue;
+ }
+
+ int const to_index0 = op0.enriched.get_next_turn_index();
+ int const to_index1 = op1.enriched.get_next_turn_index();
+ if (to_index1 >= 0
+ && to_index1 >= 0
+ && to_index0 != to_index1)
+ {
+ op0.remaining_distance = distance_measure(turn.point, turns[to_index0].point);
+ op1.remaining_distance = distance_measure(turn.point, turns[to_index1].point);
+ }
+ }
+}
+
}} // namespace detail::overlay
#endif //DOXYGEN_NO_DETAIL
@@ -239,7 +285,7 @@ inline void create_map(Turns const& turns,
\tparam Clusters type of cluster container
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
-\tparam Strategy side strategy type
+\tparam SideStrategy side strategy type
\param turns container containing intersection points
\param clusters container containing clusters
\param geometry1 \param_geometry
@@ -255,16 +301,21 @@ template
typename Clusters,
typename Geometry1, typename Geometry2,
typename RobustPolicy,
- typename Strategy
+ typename SideStrategy
>
inline void enrich_intersection_points(Turns& turns,
Clusters& clusters,
Geometry1 const& geometry1, Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
- Strategy const& strategy)
+ SideStrategy const& strategy)
{
- static const detail::overlay::operation_type for_operation
+ static const detail::overlay::operation_type target_operation
= detail::overlay::operation_from_overlay<OverlayType>::value;
+ static const detail::overlay::operation_type opposite_operation
+ = target_operation == detail::overlay::operation_union
+ ? detail::overlay::operation_intersection
+ : detail::overlay::operation_union;
+
typedef typename boost::range_value<Turns>::type turn_type;
typedef typename turn_type::turn_operation_type op_type;
typedef detail::overlay::indexed_turn_operation
@@ -278,27 +329,68 @@ inline void enrich_intersection_points(Turns& turns,
std::vector<indexed_turn_operation>
> mapped_vector_type;
+ bool has_cc = false;
bool const has_colocations
- = detail::overlay::handle_colocations<Reverse1, Reverse2>(turns,
+ = detail::overlay::handle_colocations<Reverse1, Reverse2, OverlayType>(turns,
clusters, geometry1, geometry2);
- // Discard none turns, if any
+ // Discard turns not part of target overlay
for (typename boost::range_iterator<Turns>::type
it = boost::begin(turns);
it != boost::end(turns);
++it)
{
- if (it->both(detail::overlay::operation_none))
+ turn_type& turn = *it;
+
+ if (turn.both(detail::overlay::operation_none))
+ {
+ turn.discarded = true;
+ continue;
+ }
+
+ if (turn.both(opposite_operation))
{
- it->discarded = true;
+ // For intersections, remove uu to avoid the need to travel
+ // a union (during intersection) in uu/cc clusters (e.g. #31,#32,#33)
+ // Also, for union, discard ii
+ turn.discarded = true;
+ turn.cluster_id = -1;
+ continue;
+ }
+
+ if (detail::overlay::is_self_turn<OverlayType>(turn)
+ && turn.cluster_id < 0
+ && ! turn.both(target_operation))
+ {
+ // Only keep self-uu-turns or self-ii-turns
+ turn.discarded = true;
+ turn.cluster_id = -1;
+ continue;
+ }
+
+ if (! turn.discarded
+ && turn.both(detail::overlay::operation_continue))
+ {
+ has_cc = true;
}
}
+ detail::overlay::discard_closed_turns
+ <
+ OverlayType,
+ target_operation
+ >::apply(turns, geometry1, geometry2);
+ detail::overlay::discard_open_turns
+ <
+ OverlayType,
+ target_operation
+ >::apply(turns, geometry1, geometry2);
+
// Create a map of vectors of indexed operation-types to be able
// to sort intersection points PER RING
mapped_vector_type mapped_vector;
- detail::overlay::create_map(turns, for_operation, mapped_vector);
+ detail::overlay::create_map(turns, mapped_vector);
// No const-iterator; contents of mapped copy is temporary,
// and changed by enrich
@@ -312,7 +404,7 @@ inline void enrich_intersection_points(Turns& turns,
<< mit->first << std::endl;
#endif
detail::overlay::enrich_sort<Reverse1, Reverse2>(
- mit->second, turns, for_operation,
+ mit->second, turns, target_operation,
geometry1, geometry2,
robust_policy, strategy);
}
@@ -331,8 +423,22 @@ inline void enrich_intersection_points(Turns& turns,
if (has_colocations)
{
- detail::overlay::gather_cluster_properties<Reverse1, Reverse2>(
- clusters, turns, for_operation, geometry1, geometry2);
+ // First gather cluster properties (using even clusters with
+ // discarded turns - for open turns), then clean up clusters
+ detail::overlay::gather_cluster_properties
+ <
+ Reverse1,
+ Reverse2,
+ OverlayType
+ >(clusters, turns, target_operation,
+ geometry1, geometry2, strategy);
+
+ detail::overlay::cleanup_clusters(turns, clusters);
+ }
+
+ if (has_cc)
+ {
+ detail::overlay::calculate_remaining_distance(turns);
}
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
diff --git a/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp b/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp
index 2643415343..fdffd665e4 100644
--- a/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp
+++ b/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp
@@ -37,10 +37,17 @@ struct enrichment_info
, startable(true)
, count_left(0)
, count_right(0)
+ , rank(-1)
, zone(-1)
- , only_turn_on_ring(false)
+ , region_id(-1)
+ , isolated(false)
{}
+ inline signed_size_type get_next_turn_index() const
+ {
+ return next_ip_index == -1 ? travels_to_ip_index : next_ip_index;
+ }
+
// vertex to which is free travel after this IP,
// so from "segment_index+1" to "travels_to_vertex_index", without IP-s,
// can be -1
@@ -57,8 +64,10 @@ struct enrichment_info
// Counts if polygons left/right of this operation
std::size_t count_left;
std::size_t count_right;
+ signed_size_type rank; // in cluster
signed_size_type zone; // open zone, in cluster
- bool only_turn_on_ring; // True if it is the only turn on a ring (for clusters)
+ signed_size_type region_id;
+ bool isolated;
};
diff --git a/boost/geometry/algorithms/detail/overlay/follow.hpp b/boost/geometry/algorithms/detail/overlay/follow.hpp
index 22807b5140..589e12cc2b 100644
--- a/boost/geometry/algorithms/detail/overlay/follow.hpp
+++ b/boost/geometry/algorithms/detail/overlay/follow.hpp
@@ -2,10 +2,10 @@
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014.
-// Modifications copyright (c) 2014 Oracle and/or its affiliates.
-
+// This file was modified by Oracle on 2014, 2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -55,21 +55,14 @@ template
typename Turn,
typename Operation,
typename LineString,
- typename Polygon
+ typename Polygon,
+ typename PtInPolyStrategy
>
static inline bool last_covered_by(Turn const& turn, Operation const& op,
- LineString const& linestring, Polygon const& polygon)
+ LineString const& linestring, Polygon const& polygon,
+ PtInPolyStrategy const& strategy)
{
- // Check any point between the this one and the first IP
- typedef typename geometry::point_type<LineString>::type point_type;
- point_type point_in_between;
- detail::point_on_border::midpoint_helper
- <
- point_type,
- 0, dimension<point_type>::value
- >::apply(point_in_between, *(::boost::begin(linestring) + op.seg_id.segment_index), turn.point);
-
- return geometry::covered_by(point_in_between, polygon);
+ return geometry::covered_by(range::at(linestring, op.seg_id.segment_index), polygon, strategy);
}
@@ -78,17 +71,19 @@ template
typename Turn,
typename Operation,
typename LineString,
- typename Polygon
+ typename Polygon,
+ typename PtInPolyStrategy
>
static inline bool is_leaving(Turn const& turn, Operation const& op,
bool entered, bool first,
- LineString const& linestring, Polygon const& polygon)
+ LineString const& linestring, Polygon const& polygon,
+ PtInPolyStrategy const& strategy)
{
if (op.operation == operation_union)
{
return entered
|| turn.method == method_crosses
- || (first && last_covered_by(turn, op, linestring, polygon))
+ || (first && last_covered_by(turn, op, linestring, polygon, strategy))
;
}
return false;
@@ -100,11 +95,13 @@ template
typename Turn,
typename Operation,
typename LineString,
- typename Polygon
+ typename Polygon,
+ typename PtInPolyStrategy
>
static inline bool is_staying_inside(Turn const& turn, Operation const& op,
bool entered, bool first,
- LineString const& linestring, Polygon const& polygon)
+ LineString const& linestring, Polygon const& polygon,
+ PtInPolyStrategy const& strategy)
{
if (turn.method == method_crosses)
{
@@ -115,7 +112,7 @@ static inline bool is_staying_inside(Turn const& turn, Operation const& op,
if (is_entering(turn, op))
{
- return entered || (first && last_covered_by(turn, op, linestring, polygon));
+ return entered || (first && last_covered_by(turn, op, linestring, polygon, strategy));
}
return false;
@@ -126,14 +123,16 @@ template
typename Turn,
typename Operation,
typename Linestring,
- typename Polygon
+ typename Polygon,
+ typename PtInPolyStrategy
>
static inline bool was_entered(Turn const& turn, Operation const& op, bool first,
- Linestring const& linestring, Polygon const& polygon)
+ Linestring const& linestring, Polygon const& polygon,
+ PtInPolyStrategy const& strategy)
{
if (first && (turn.method == method_collinear || turn.method == method_equal))
{
- return last_covered_by(turn, op, linestring, polygon);
+ return last_covered_by(turn, op, linestring, polygon, strategy);
}
return false;
}
@@ -158,6 +157,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
typename LineString,
typename Point,
typename Operation,
+ typename SideStrategy,
typename RobustPolicy
>
static inline void enter(LineStringOut& current_piece,
@@ -165,6 +165,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
segment_identifier& segment_id,
signed_size_type , Point const& point,
Operation const& operation,
+ SideStrategy const& ,
RobustPolicy const& ,
OutputIterator& )
{
@@ -181,6 +182,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
typename LineString,
typename Point,
typename Operation,
+ typename SideStrategy,
typename RobustPolicy
>
static inline void leave(LineStringOut& current_piece,
@@ -188,6 +190,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
segment_identifier& segment_id,
signed_size_type index, Point const& point,
Operation const& ,
+ SideStrategy const& strategy,
RobustPolicy const& robust_policy,
OutputIterator& out)
{
@@ -196,7 +199,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
detail::copy_segments::copy_segments_linestring
<
false, RemoveSpikes
- >::apply(linestring, segment_id, index, robust_policy, current_piece);
+ >::apply(linestring, segment_id, index, strategy, robust_policy, current_piece);
detail::overlay::append_no_duplicates(current_piece, point);
if (::boost::size(current_piece) > 1)
{
@@ -235,17 +238,9 @@ struct action_selector<overlay_intersection, RemoveSpikes>
return entered;
}
- template
- <
- typename Point,
- typename Geometry,
- typename RobustPolicy
- >
- static inline bool included(Point const& point,
- Geometry const& geometry,
- RobustPolicy const& )
+ static inline bool included(int inside_value)
{
- return geometry::covered_by(point, geometry);
+ return inside_value >= 0; // covered_by
}
};
@@ -263,6 +258,7 @@ struct action_selector<overlay_difference, RemoveSpikes>
typename LineString,
typename Point,
typename Operation,
+ typename SideStrategy,
typename RobustPolicy
>
static inline void enter(LineStringOut& current_piece,
@@ -270,11 +266,12 @@ struct action_selector<overlay_difference, RemoveSpikes>
segment_identifier& segment_id,
signed_size_type index, Point const& point,
Operation const& operation,
+ SideStrategy const& strategy,
RobustPolicy const& robust_policy,
OutputIterator& out)
{
normal_action::leave(current_piece, linestring, segment_id, index,
- point, operation, robust_policy, out);
+ point, operation, strategy, robust_policy, out);
}
template
@@ -284,6 +281,7 @@ struct action_selector<overlay_difference, RemoveSpikes>
typename LineString,
typename Point,
typename Operation,
+ typename SideStrategy,
typename RobustPolicy
>
static inline void leave(LineStringOut& current_piece,
@@ -291,11 +289,12 @@ struct action_selector<overlay_difference, RemoveSpikes>
segment_identifier& segment_id,
signed_size_type index, Point const& point,
Operation const& operation,
+ SideStrategy const& strategy,
RobustPolicy const& robust_policy,
OutputIterator& out)
{
normal_action::enter(current_piece, linestring, segment_id, index,
- point, operation, robust_policy, out);
+ point, operation, strategy, robust_policy, out);
}
template
@@ -319,17 +318,9 @@ struct action_selector<overlay_difference, RemoveSpikes>
return ! normal_action::is_entered(entered);
}
- template
- <
- typename Point,
- typename Geometry,
- typename RobustPolicy
- >
- static inline bool included(Point const& point,
- Geometry const& geometry,
- RobustPolicy const& robust_policy)
+ static inline bool included(int inside_value)
{
- return ! normal_action::included(point, geometry, robust_policy);
+ return ! normal_action::included(inside_value);
}
};
@@ -403,33 +394,27 @@ class follow
public :
- template
- <
- typename Point,
- typename Geometry,
- typename RobustPolicy
- >
- static inline bool included(Point const& point,
- Geometry const& geometry,
- RobustPolicy const& robust_policy)
+ static inline bool included(int inside_value)
{
return following::action_selector
<
OverlayType, RemoveSpikes
- >::included(point, geometry, robust_policy);
+ >::included(inside_value);
}
template
<
typename Turns,
typename OutputIterator,
- typename RobustPolicy
+ typename RobustPolicy,
+ typename Strategy
>
static inline OutputIterator apply(LineString const& linestring, Polygon const& polygon,
detail::overlay::operation_type , // TODO: this parameter might be redundant
Turns& turns,
RobustPolicy const& robust_policy,
- OutputIterator out)
+ OutputIterator out,
+ Strategy const& strategy)
{
typedef typename boost::range_iterator<Turns>::type turn_iterator;
typedef typename boost::range_value<Turns>::type turn_type;
@@ -440,6 +425,12 @@ public :
typedef following::action_selector<OverlayType, RemoveSpikes> action;
+ typename Strategy::template point_in_geometry_strategy
+ <
+ LineString, Polygon
+ >::type const pt_in_poly_strategy
+ = strategy.template get_point_in_geometry_strategy<LineString, Polygon>();
+
// Sort intersection points on segments-along-linestring, and distance
// (like in enrich is done for poly/poly)
std::sort(boost::begin(turns), boost::end(turns), sort_on_segment<turn_type>());
@@ -454,13 +445,13 @@ public :
{
turn_operation_iterator_type iit = boost::begin(it->operations);
- if (following::was_entered(*it, *iit, first, linestring, polygon))
+ if (following::was_entered(*it, *iit, first, linestring, polygon, pt_in_poly_strategy))
{
debug_traverse(*it, *iit, "-> Was entered");
entered = true;
}
- if (following::is_staying_inside(*it, *iit, entered, first, linestring, polygon))
+ if (following::is_staying_inside(*it, *iit, entered, first, linestring, polygon, pt_in_poly_strategy))
{
debug_traverse(*it, *iit, "-> Staying inside");
@@ -473,17 +464,17 @@ public :
entered = true;
action::enter(current_piece, linestring, current_segment_id,
iit->seg_id.segment_index, it->point, *iit,
- robust_policy,
+ strategy, robust_policy,
out);
}
- else if (following::is_leaving(*it, *iit, entered, first, linestring, polygon))
+ else if (following::is_leaving(*it, *iit, entered, first, linestring, polygon, pt_in_poly_strategy))
{
debug_traverse(*it, *iit, "-> Leaving");
entered = false;
action::leave(current_piece, linestring, current_segment_id,
iit->seg_id.segment_index, it->point, *iit,
- robust_policy,
+ strategy, robust_policy,
out);
}
first = false;
@@ -497,7 +488,7 @@ public :
>::apply(linestring,
current_segment_id,
static_cast<signed_size_type>(boost::size(linestring) - 1),
- robust_policy,
+ strategy, robust_policy,
current_piece);
}
diff --git a/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp b/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
index c249ff57ff..2a374bf0b0 100644
--- a/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
@@ -2,12 +2,14 @@
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+// Copyright (c) 2014-2017, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
-// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_LINEAR_LINEAR_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_LINEAR_LINEAR_HPP
@@ -183,7 +185,8 @@ protected:
typename TurnIterator,
typename TurnOperationIterator,
typename SegmentIdentifier,
- typename OutputIterator
+ typename OutputIterator,
+ typename SideStrategy
>
static inline OutputIterator
process_turn(TurnIterator it,
@@ -193,7 +196,8 @@ protected:
Linestring const& linestring,
LinestringOut& current_piece,
SegmentIdentifier& current_segment_id,
- OutputIterator oit)
+ OutputIterator oit,
+ SideStrategy const& strategy)
{
// We don't rescale linear/linear
detail::no_rescale_policy robust_policy;
@@ -208,7 +212,7 @@ protected:
action::enter(current_piece, linestring,
current_segment_id,
op_it->seg_id.segment_index,
- it->point, *op_it, robust_policy, oit);
+ it->point, *op_it, strategy, robust_policy, oit);
}
++enter_count;
}
@@ -223,7 +227,7 @@ protected:
action::leave(current_piece, linestring,
current_segment_id,
op_it->seg_id.segment_index,
- it->point, *op_it, robust_policy, oit);
+ it->point, *op_it, strategy, robust_policy, oit);
}
}
else if ( FollowIsolatedPoints
@@ -249,14 +253,16 @@ protected:
template
<
typename SegmentIdentifier,
- typename OutputIterator
+ typename OutputIterator,
+ typename SideStrategy
>
static inline OutputIterator
process_end(bool entered,
Linestring const& linestring,
SegmentIdentifier const& current_segment_id,
LinestringOut& current_piece,
- OutputIterator oit)
+ OutputIterator oit,
+ SideStrategy const& strategy)
{
if ( action::is_entered(entered) )
{
@@ -269,6 +275,7 @@ protected:
>::apply(linestring,
current_segment_id,
static_cast<signed_size_type>(boost::size(linestring) - 1),
+ strategy,
robust_policy,
current_piece);
}
@@ -283,11 +290,12 @@ protected:
}
public:
- template <typename TurnIterator, typename OutputIterator>
+ template <typename TurnIterator, typename OutputIterator, typename SideStrategy>
static inline OutputIterator
apply(Linestring const& linestring, Linear const&,
TurnIterator first, TurnIterator beyond,
- OutputIterator oit)
+ OutputIterator oit,
+ SideStrategy const& strategy)
{
// Iterate through all intersection points (they are
// ordered along the each line)
@@ -304,7 +312,8 @@ public:
entered, enter_count,
linestring,
current_piece, current_segment_id,
- oit);
+ oit,
+ strategy);
}
#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
@@ -318,7 +327,8 @@ public:
return process_end(entered, linestring,
current_segment_id, current_piece,
- oit);
+ oit,
+ strategy);
}
};
@@ -413,11 +423,12 @@ protected:
};
public:
- template <typename TurnIterator, typename OutputIterator>
+ template <typename TurnIterator, typename OutputIterator, typename SideStrategy>
static inline OutputIterator
apply(MultiLinestring const& multilinestring, Linear const& linear,
TurnIterator first, TurnIterator beyond,
- OutputIterator oit)
+ OutputIterator oit,
+ SideStrategy const& strategy)
{
BOOST_GEOMETRY_ASSERT( first != beyond );
@@ -447,7 +458,7 @@ public:
has_other_multi_id(current_multi_id));
oit = Base::apply(*(ls_first + current_multi_id),
- linear, per_ls_current, per_ls_next, oit);
+ linear, per_ls_current, per_ls_next, oit, strategy);
signed_size_type next_multi_id = -1;
linestring_iterator ls_next = ls_beyond;
diff --git a/boost/geometry/algorithms/detail/overlay/get_relative_order.hpp b/boost/geometry/algorithms/detail/overlay/get_relative_order.hpp
index ea9aa29f19..2eec6af665 100644
--- a/boost/geometry/algorithms/detail/overlay/get_relative_order.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_relative_order.hpp
@@ -2,6 +2,11 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -31,20 +36,15 @@ namespace detail { namespace overlay
but we still need to know which comes first.
Therefore, it is useful that using sides we are able to discover this.
*/
-template <typename Point1>
struct get_relative_order
{
- typedef typename strategy::side::services::default_strategy
- <
- typename cs_tag<Point1>::type
- >::type strategy;
-
- template <typename Point>
+ template <typename Point, typename SideStrategy>
static inline int value_via_product(Point const& ti, Point const& tj,
- Point const& ui, Point const& uj, int factor)
+ Point const& ui, Point const& uj, int factor,
+ SideStrategy const& strategy)
{
- int const side_ti_u = strategy::apply(ti, tj, ui);
- int const side_tj_u = strategy::apply(ti, tj, uj);
+ int const side_ti_u = strategy.apply(ti, tj, ui);
+ int const side_tj_u = strategy.apply(ti, tj, uj);
#ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER
std::cout << (factor == 1 ? " r//s " : " s//r ")
@@ -57,13 +57,15 @@ struct get_relative_order
}
+ template <typename Point1, typename SideStrategy>
static inline int apply(
Point1 const& pi, Point1 const& pj,
Point1 const& ri, Point1 const& rj,
- Point1 const& si, Point1 const& sj)
+ Point1 const& si, Point1 const& sj,
+ SideStrategy const& strategy)
{
- int const side_ri_p = strategy::apply(pi, pj, ri);
- int const side_si_p = strategy::apply(pi, pj, si);
+ int const side_ri_p = strategy.apply(pi, pj, ri);
+ int const side_si_p = strategy.apply(pi, pj, si);
#ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER
int const side_rj_p = strategy::apply(pi, pj, rj);
@@ -72,10 +74,10 @@ struct get_relative_order
std::cout << " s//p: " << side_si_p << " / " << side_sj_p;
#endif
- int value = value_via_product(si, sj, ri, rj, 1);
+ int value = value_via_product(si, sj, ri, rj, 1, strategy);
if (value == 0)
{
- value = value_via_product(ri, rj, si, sj, -1);
+ value = value_via_product(ri, rj, si, sj, -1, strategy);
}
int const order = side_ri_p * side_ri_p * side_si_p * value;
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
index 08bc342186..895952c8fc 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
@@ -190,6 +190,7 @@ struct touch_interior : public base_turn_handler
// Q turns left on the right side of P (test "MR3")
// Both directions for "intersection"
both(ti, operation_intersection);
+ ti.touch_only = true;
}
else if (side_qi_p == 1 && side_qk_p == 1 && side_qk_q == -1)
{
@@ -197,6 +198,7 @@ struct touch_interior : public base_turn_handler
// Union: take both operation
// Intersection: skip
both(ti, operation_union);
+ ti.touch_only = true;
}
else if (side_qi_p == side_qk_p && side_qi_p == side_qk_q)
{
@@ -207,6 +209,7 @@ struct touch_interior : public base_turn_handler
unsigned int index = side_qk_q == 1 ? index_q : index_p;
ti.operations[index].operation = operation_union;
ti.operations[1 - index].operation = operation_intersection;
+ ti.touch_only = true;
}
else if (side_qk_p == 0)
{
@@ -346,6 +349,7 @@ struct touch : public base_turn_handler
if (side_pk_q2 == -side_qk_q)
{
ui_else_iu(! q_turns_left, ti);
+ ti.touch_only = true;
return;
}
@@ -358,6 +362,10 @@ struct touch : public base_turn_handler
{
ti.operations[1].operation = operation_blocked;
}
+ else
+ {
+ ti.touch_only = true;
+ }
//block_second(block_q, ti);
return;
}
@@ -373,6 +381,10 @@ struct touch : public base_turn_handler
: side_qi_p1 == 1 || side_qk_p1 == 1
? operation_union
: operation_intersection;
+ if (! block_q)
+ {
+ ti.touch_only = true;
+ }
return;
}
@@ -400,6 +412,7 @@ struct touch : public base_turn_handler
if (side_pk_q1 == side_qk_p1)
{
uu_else_ii(right_to_left, ti);
+ ti.touch_only = true;
return;
}
}
@@ -418,6 +431,7 @@ struct touch : public base_turn_handler
if (side_pk_q2 == side_qk_p1)
{
ui_else_iu(right_to_left, ti);
+ ti.touch_only = true;
return;
}
}
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp
index 5f2cb07faf..f8247cd240 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp
@@ -66,7 +66,7 @@ struct side_calculator
Qj const& m_qj;
Qk const& m_qk;
- SideStrategy const& m_side_strategy;
+ SideStrategy m_side_strategy;
};
template <typename Point1, typename Point2, typename RobustPolicy>
diff --git a/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/boost/geometry/algorithms/detail/overlay/get_turns.hpp
index 4e97a84a37..f88dfe8422 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turns.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turns.hpp
@@ -1,7 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014, 2016, 2017.
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
@@ -90,6 +90,9 @@ struct no_interrupt_policy
{
static bool const enabled = false;
+ // variable required by self_get_turn_points::get_turns
+ static bool const has_intersections = false;
+
template <typename Range>
static inline bool apply(Range const&)
{
@@ -230,7 +233,7 @@ public :
// section 2: [--------------]
// section 1: |----|---|---|---|---|
for (prev1 = it1++, next1++;
- it1 != end1 && ! detail::section::exceeding<0>(dir1, *prev1, sec2.bounding_box, robust_policy);
+ it1 != end1 && ! detail::section::exceeding<0>(dir1, *prev1, sec1.bounding_box, sec2.bounding_box, robust_policy);
++prev1, ++it1, ++index1, ++next1, ++ndi1)
{
ever_circling_iterator<range1_iterator> nd_next1(
@@ -248,7 +251,7 @@ public :
next2++;
for (prev2 = it2++, next2++;
- it2 != end2 && ! detail::section::exceeding<0>(dir2, *prev2, sec1.bounding_box, robust_policy);
+ it2 != end2 && ! detail::section::exceeding<0>(dir2, *prev2, sec2.bounding_box, sec1.bounding_box, robust_policy);
++prev2, ++it2, ++index2, ++next2, ++ndi2)
{
bool skip = same_source;
@@ -356,7 +359,7 @@ private :
// skips to the begin-point, we loose the index or have to recalculate it)
// So we mimic it here
template <typename Range, typename Section, typename Box, typename RobustPolicy>
- static inline void get_start_point_iterator(Section & section,
+ static inline void get_start_point_iterator(Section const& section,
Range const& range,
typename boost::range_iterator<Range const>::type& it,
typename boost::range_iterator<Range const>::type& prev,
@@ -370,7 +373,7 @@ private :
// Mimic section-iterator:
// Skip to point such that section interects other box
prev = it++;
- for(; it != end && detail::section::preceding<0>(dir, *it, other_bounding_box, robust_policy);
+ for(; it != end && detail::section::preceding<0>(dir, *it, section.bounding_box, other_bounding_box, robust_policy);
prev = it++, index++, ndi++)
{}
// Go back one step because we want to start completely preceding
@@ -418,6 +421,7 @@ struct section_visitor
{
if (! detail::disjoint::disjoint_box_box(sec1.bounding_box, sec2.bounding_box))
{
+ // false if interrupted
return get_turns_in_sections
<
Geometry1,
@@ -425,13 +429,12 @@ struct section_visitor
Reverse1, Reverse2,
Section, Section,
TurnPolicy
- >::apply(
- m_source_id1, m_geometry1, sec1,
- m_source_id2, m_geometry2, sec2,
- false,
- m_intersection_strategy,
- m_rescale_policy,
- m_turns, m_interrupt_policy);
+ >::apply(m_source_id1, m_geometry1, sec1,
+ m_source_id2, m_geometry2, sec2,
+ false,
+ m_intersection_strategy,
+ m_rescale_policy,
+ m_turns, m_interrupt_policy);
}
return true;
}
@@ -473,10 +476,13 @@ public:
sections_type sec1, sec2;
typedef boost::mpl::vector_c<std::size_t, 0, 1> dimensions;
+ typename IntersectionStrategy::envelope_strategy_type const
+ envelope_strategy = intersection_strategy.get_envelope_strategy();
+
geometry::sectionalize<Reverse1, dimensions>(geometry1, robust_policy,
- sec1, 0);
+ sec1, envelope_strategy, 0);
geometry::sectionalize<Reverse2, dimensions>(geometry2, robust_policy,
- sec2, 1);
+ sec2, envelope_strategy, 1);
// ... and then partition them, intersecting overlapping sections in visitor method
section_visitor
diff --git a/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp b/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
index 400ed3b881..f3311b34e9 100644
--- a/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
+++ b/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
@@ -2,6 +2,11 @@
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -262,15 +267,6 @@ inline void handle_colocation_cluster(Turns& turns,
add_cluster_id(other_op, cluster_per_segment, ref_id);
id = ref_id;
}
-
- // In case of colocated xx turns, all other turns may NOT be
- // followed at all. xx cannot be discarded (otherwise colocated
- // turns are followed).
- if (ref_turn.both(operation_blocked))
- {
- turn.discarded = true;
- // We can either set or not set colocated because it is not effective on blocked turns
- }
}
else
{
@@ -331,11 +327,7 @@ inline void assign_cluster_to_turns(Turns& turns,
}
}
-template
-<
- typename Turns,
- typename Clusters
->
+template <typename Turns, typename Clusters>
inline void remove_clusters(Turns& turns, Clusters& clusters)
{
typename Clusters::iterator it = clusters.begin();
@@ -350,17 +342,44 @@ inline void remove_clusters(Turns& turns, Clusters& clusters)
= current_it->second.turn_indices;
if (turn_indices.size() == 1)
{
- signed_size_type turn_index = *turn_indices.begin();
+ signed_size_type const turn_index = *turn_indices.begin();
turns[turn_index].cluster_id = -1;
clusters.erase(current_it);
}
}
}
+template <typename Turns, typename Clusters>
+inline void cleanup_clusters(Turns& turns, Clusters& clusters)
+{
+ // Removes discarded turns from clusters
+ for (typename Clusters::iterator mit = clusters.begin();
+ mit != clusters.end(); ++mit)
+ {
+ cluster_info& cinfo = mit->second;
+ std::set<signed_size_type>& ids = cinfo.turn_indices;
+ for (std::set<signed_size_type>::iterator sit = ids.begin();
+ sit != ids.end(); /* no increment */)
+ {
+ std::set<signed_size_type>::iterator current_it = sit;
+ ++sit;
+
+ signed_size_type const turn_index = *current_it;
+ if (turns[turn_index].discarded)
+ {
+ ids.erase(current_it);
+ }
+ }
+ }
+
+ remove_clusters(turns, clusters);
+}
+
template <typename Turn, typename IdSet>
inline void discard_ie_turn(Turn& turn, IdSet& ids, signed_size_type id)
{
turn.discarded = true;
+ // Set cluster id to -1, but don't clear colocated flags
turn.cluster_id = -1;
// To remove it later from clusters
ids.insert(id);
@@ -378,6 +397,13 @@ inline bool is_ie_turn(segment_identifier const& ext_seg_0,
segment_identifier const& int_seg_0,
segment_identifier const& other_seg_1)
{
+ if (ext_seg_0.source_index == ext_seg_1.source_index)
+ {
+ // External turn is a self-turn, dont discard internal turn for this
+ return false;
+ }
+
+
// Compares two segment identifiers from two turns (external / one internal)
// From first turn [0], both are from same polygon (multi_index),
@@ -411,6 +437,7 @@ inline bool is_ie_turn(segment_identifier const& ext_seg_0,
template
<
bool Reverse0, bool Reverse1, // Reverse interpretation interior/exterior
+ overlay_type OverlayType,
typename Turns,
typename Clusters
>
@@ -435,19 +462,6 @@ inline void discard_interior_exterior_turns(Turns& turns, Clusters& clusters)
segment_identifier const& seg_0 = turn.operations[0].seg_id;
segment_identifier const& seg_1 = turn.operations[1].seg_id;
- if (turn.both(operation_intersection)
- && Reverse0 == Reverse1)
- {
- if ( is_interior<Reverse0>(seg_0)
- && is_interior<Reverse1>(seg_1))
- {
- // ii touch with, two interior rings
- discard_ie_turn(turn, ids_to_remove, *it);
- }
-
- continue;
- }
-
if (! (turn.both(operation_union)
|| turn.combination(operation_union, operation_blocked)))
{
@@ -487,6 +501,53 @@ inline void discard_interior_exterior_turns(Turns& turns, Clusters& clusters)
}
}
+template
+<
+ typename Turns,
+ typename Clusters
+>
+inline void set_colocation(Turns& turns, Clusters const& clusters)
+{
+ typedef std::set<signed_size_type>::const_iterator set_iterator;
+ typedef typename boost::range_value<Turns>::type turn_type;
+
+ for (typename Clusters::const_iterator cit = clusters.begin();
+ cit != clusters.end(); ++cit)
+ {
+ cluster_info const& cinfo = cit->second;
+ std::set<signed_size_type> const& ids = cinfo.turn_indices;
+
+ bool has_ii = false;
+ bool has_uu = false;
+ for (set_iterator it = ids.begin(); it != ids.end(); ++it)
+ {
+ turn_type const& turn = turns[*it];
+ if (turn.both(operation_intersection))
+ {
+ has_ii = true;
+ }
+ if (turn.both(operation_union) || turn.combination(operation_union, operation_blocked))
+ {
+ has_uu = true;
+ }
+ }
+ if (has_ii || has_uu)
+ {
+ for (set_iterator it = ids.begin(); it != ids.end(); ++it)
+ {
+ turn_type& turn = turns[*it];
+ if (has_ii)
+ {
+ turn.colocated_ii = true;
+ }
+ if (has_uu)
+ {
+ turn.colocated_uu = true;
+ }
+ }
+ }
+ }
+}
// Checks colocated turns and flags combinations of uu/other, possibly a
// combination of a ring touching another geometry's interior ring which is
@@ -498,6 +559,7 @@ inline void discard_interior_exterior_turns(Turns& turns, Clusters& clusters)
template
<
bool Reverse1, bool Reverse2,
+ overlay_type OverlayType,
typename Turns,
typename Clusters,
typename Geometry1,
@@ -578,12 +640,13 @@ inline bool handle_colocations(Turns& turns, Clusters& clusters,
}
assign_cluster_to_turns(turns, clusters, cluster_per_segment);
+ set_colocation(turns, clusters);
discard_interior_exterior_turns
<
do_reverse<geometry::point_order<Geometry1>::value>::value != Reverse1,
- do_reverse<geometry::point_order<Geometry2>::value>::value != Reverse2
+ do_reverse<geometry::point_order<Geometry2>::value>::value != Reverse2,
+ OverlayType
>(turns, clusters);
- remove_clusters(turns, clusters);
#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_COLOCATIONS)
std::cout << "*** Colocations " << map.size() << std::endl;
@@ -598,7 +661,8 @@ inline bool handle_colocations(Turns& turns, Clusters& clusters,
std::cout << geometry::wkt(turns[toi.turn_index].point)
<< std::boolalpha
<< " discarded=" << turns[toi.turn_index].discarded
- << " colocated=" << turns[toi.turn_index].colocated
+ << " colocated(uu)=" << turns[toi.turn_index].colocated_uu
+ << " colocated(ii)=" << turns[toi.turn_index].colocated_ii
<< " " << operation_char(turns[toi.turn_index].operations[0].operation)
<< " " << turns[toi.turn_index].operations[0].seg_id
<< " " << turns[toi.turn_index].operations[0].fraction
@@ -634,14 +698,17 @@ struct is_turn_index
template
<
bool Reverse1, bool Reverse2,
+ overlay_type OverlayType,
typename Turns,
typename Clusters,
typename Geometry1,
- typename Geometry2
+ typename Geometry2,
+ typename SideStrategy
>
inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
operation_type for_operation,
- Geometry1 const& geometry1, Geometry2 const& geometry2)
+ Geometry1 const& geometry1, Geometry2 const& geometry2,
+ SideStrategy const& strategy)
{
typedef typename boost::range_value<Turns>::type turn_type;
typedef typename turn_type::point_type point_type;
@@ -651,7 +718,7 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
// right side
typedef sort_by_side::side_sorter
<
- Reverse1, Reverse2, point_type, std::less<int>
+ Reverse1, Reverse2, OverlayType, point_type, SideStrategy, std::less<int>
> sbs_type;
for (typename Clusters::iterator mit = clusters.begin();
@@ -664,11 +731,11 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
continue;
}
- sbs_type sbs;
+ sbs_type sbs(strategy);
point_type turn_point; // should be all the same for all turns in cluster
bool first = true;
- for (typename std::set<signed_size_type>::const_iterator sit = ids.begin();
+ for (std::set<signed_size_type>::const_iterator sit = ids.begin();
sit != ids.end(); ++sit)
{
signed_size_type turn_index = *sit;
@@ -689,6 +756,8 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
sbs.find_open();
sbs.assign_zones(for_operation);
+ cinfo.open_count = sbs.open_count(for_operation);
+
// Unset the startable flag for all 'closed' zones
for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
{
@@ -696,6 +765,11 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
turn_type& turn = turns[ranked.turn_index];
turn_operation_type& op = turn.operations[ranked.operation_index];
+ if (for_operation == operation_union && cinfo.open_count == 0)
+ {
+ op.enriched.startable = false;
+ }
+
if (ranked.direction != sort_by_side::dir_to)
{
continue;
@@ -703,6 +777,7 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
op.enriched.count_left = ranked.count_left;
op.enriched.count_right = ranked.count_right;
+ op.enriched.rank = ranked.rank;
op.enriched.zone = ranked.zone;
if ((for_operation == operation_union
@@ -714,7 +789,6 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
}
}
- cinfo.open_count = sbs.open_count(for_operation);
}
}
diff --git a/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp b/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp
new file mode 100644
index 0000000000..39c55db759
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp
@@ -0,0 +1,143 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2017 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the 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_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_SELF_TURNS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_SELF_TURNS_HPP
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/algorithms/detail/overlay/is_self_turn.hpp>
+#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
+#include <boost/geometry/algorithms/within.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+struct discard_turns
+{
+ template <typename Turns, typename Geometry0, typename Geometry1>
+ static inline
+ void apply(Turns& , Geometry0 const& , Geometry1 const& )
+ {}
+};
+
+template <overlay_type OverlayType, operation_type OperationType>
+struct discard_closed_turns : discard_turns {};
+
+// It is only implemented for operation_union, not in buffer
+template <>
+struct discard_closed_turns<overlay_union, operation_union>
+{
+
+ template <typename Turns, typename Geometry0, typename Geometry1>
+ static inline
+ void apply(Turns& turns,
+ Geometry0 const& geometry0, Geometry1 const& geometry1)
+ {
+ typedef typename boost::range_value<Turns>::type turn_type;
+
+ for (typename boost::range_iterator<Turns>::type
+ it = boost::begin(turns);
+ it != boost::end(turns);
+ ++it)
+ {
+ turn_type& turn = *it;
+
+ if (turn.cluster_id >= 0
+ || turn.discarded
+ || ! is_self_turn<overlay_union>(turn))
+ {
+ continue;
+ }
+
+ bool const within =
+ turn.operations[0].seg_id.source_index == 0
+ ? geometry::within(turn.point, geometry1)
+ : geometry::within(turn.point, geometry0);
+
+ if (within)
+ {
+ // It is in the interior of the other geometry
+ turn.discarded = true;
+ }
+ }
+ }
+};
+
+struct discard_self_intersection_turns
+{
+ template <typename Turns, typename Geometry0, typename Geometry1>
+ static inline
+ void apply(Turns& turns,
+ Geometry0 const& geometry0, Geometry1 const& geometry1)
+ {
+ typedef typename boost::range_value<Turns>::type turn_type;
+
+ for (typename boost::range_iterator<Turns>::type
+ it = boost::begin(turns);
+ it != boost::end(turns);
+ ++it)
+ {
+ turn_type& turn = *it;
+
+ if (turn.cluster_id >= 0
+ || turn.discarded
+ || ! is_self_turn<overlay_intersection>(turn))
+ {
+ continue;
+ }
+
+ segment_identifier const& id0 = turn.operations[0].seg_id;
+ segment_identifier const& id1 = turn.operations[1].seg_id;
+ if (id0.multi_index != id1.multi_index
+ || (id0.ring_index == -1 && id1.ring_index == -1)
+ || (id0.ring_index >= 0 && id1.ring_index >= 0))
+ {
+ // Not an ii ring (int/ext) on same ring
+ continue;
+ }
+
+ // It is a non co-located ii self-turn
+ // Check if it is within the other geometry
+ // If not, it can be ignored
+
+ bool const within =
+ turn.operations[0].seg_id.source_index == 0
+ ? geometry::within(turn.point, geometry1)
+ : geometry::within(turn.point, geometry0);
+
+ if (! within)
+ {
+ // It is not within another geometry, discard the turn
+ turn.discarded = true;
+ }
+ }
+ }
+};
+
+template <overlay_type OverlayType, operation_type OperationType>
+struct discard_open_turns : discard_turns {};
+
+// Handler it for intersection
+template <>
+struct discard_open_turns<overlay_intersection, operation_intersection>
+ : discard_self_intersection_turns {};
+
+// For difference, it should be done in a different way (TODO)
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_SELF_TURNS_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
index 3244480f48..7106e7b480 100644
--- a/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
+++ b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
@@ -30,10 +30,11 @@
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/detail/overlay/clip_linestring.hpp>
+#include <boost/geometry/algorithms/detail/overlay/follow.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
-#include <boost/geometry/algorithms/detail/overlay/follow.hpp>
+#include <boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp>
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
@@ -288,6 +289,27 @@ struct intersection_of_linestring_with_areal
>::apply(boost::begin(turns), boost::end(turns));
}
+ template <typename Turns>
+ static inline int inside_or_outside_turn(Turns const& turns)
+ {
+ using namespace overlay;
+ for (typename Turns::const_iterator it = turns.begin();
+ it != turns.end(); ++it)
+ {
+ operation_type op0 = it->operations[0].operation;
+ operation_type op1 = it->operations[1].operation;
+ if (op0 == operation_intersection && op1 == operation_intersection)
+ {
+ return 1; // inside
+ }
+ else if (op0 == operation_union && op1 == operation_union)
+ {
+ return -1; // outside
+ }
+ }
+ return 0;
+ }
+
template
<
typename LineString, typename Areal,
@@ -331,19 +353,21 @@ struct intersection_of_linestring_with_areal
if (no_crossing_turns_or_empty(turns))
{
- // No intersection points, it is either completely
+ // No intersection points, it is either
// inside (interior + borders)
- // or completely outside
+ // or outside (exterior + borders)
- // Use border point (on a segment) to check this
- // (because turn points might skip some cases)
- point_type border_point;
- if (! geometry::point_on_border(border_point, linestring, true))
+ // analyse the turns
+ int inside_value = inside_or_outside_turn(turns);
+ if (inside_value == 0)
{
- return out;
+ // if needed analyse points of a linestring
+ // NOTE: range_in_geometry checks points of a linestring
+ // until a point inside/outside areal is found
+ inside_value = overlay::range_in_geometry(linestring, areal, strategy);
}
-
- if (follower::included(border_point, areal, robust_policy))
+ // add point to the output if conditions are met
+ if (inside_value != 0 && follower::included(inside_value))
{
LineStringOut copy;
geometry::convert(linestring, copy);
@@ -365,7 +389,7 @@ struct intersection_of_linestring_with_areal
(
linestring, areal,
geometry::detail::overlay::operation_intersection,
- turns, robust_policy, out
+ turns, robust_policy, out, strategy
);
}
};
diff --git a/boost/geometry/algorithms/detail/overlay/is_self_turn.hpp b/boost/geometry/algorithms/detail/overlay/is_self_turn.hpp
new file mode 100644
index 0000000000..9cb7a0fca9
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/is_self_turn.hpp
@@ -0,0 +1,68 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2017-2017 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the 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_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_IS_SELF_TURN_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_IS_SELF_TURN_HPP
+
+#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+template <overlay_type OverlayType>
+struct is_self_turn_check
+{
+ template <typename Turn>
+ static inline bool apply(Turn const& turn)
+ {
+ return turn.operations[0].seg_id.source_index
+ == turn.operations[1].seg_id.source_index;
+ }
+};
+
+template <>
+struct is_self_turn_check<overlay_buffer>
+{
+ template <typename Turn>
+ static inline bool apply(Turn const& turn)
+ {
+ return false;
+ }
+};
+
+template <>
+struct is_self_turn_check<overlay_dissolve>
+{
+ template <typename Turn>
+ static inline bool apply(Turn const& turn)
+ {
+ return false;
+ }
+};
+
+
+template <overlay_type OverlayType, typename Turn>
+bool is_self_turn(Turn const& turn)
+{
+ return is_self_turn_check<OverlayType>::apply(turn);
+}
+
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_IS_SELF_TURN_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp b/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp
index 21868a2939..dd30635ee2 100644
--- a/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp
+++ b/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp
@@ -2,6 +2,11 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -60,6 +65,7 @@ template
typename Indexed,
typename Geometry1, typename Geometry2,
typename RobustPolicy,
+ typename SideStrategy,
bool Reverse1, bool Reverse2
>
struct less_by_segment_ratio
@@ -68,12 +74,14 @@ struct less_by_segment_ratio
, operation_type for_operation
, Geometry1 const& geometry1
, Geometry2 const& geometry2
- , RobustPolicy const& robust_policy)
+ , RobustPolicy const& robust_policy
+ , SideStrategy const& strategy)
: m_turns(turns)
, m_for_operation(for_operation)
, m_geometry1(geometry1)
, m_geometry2(geometry2)
, m_robust_policy(robust_policy)
+ , m_strategy(strategy)
{
}
@@ -84,6 +92,7 @@ private :
Geometry1 const& m_geometry1;
Geometry2 const& m_geometry2;
RobustPolicy const& m_robust_policy;
+ SideStrategy const& m_strategy;
typedef typename geometry::point_type<Geometry1>::type point_type;
@@ -108,13 +117,8 @@ private :
*right.other_seg_id,
si, sj);
- typedef typename strategy::side::services::default_strategy
- <
- typename cs_tag<point_type>::type
- >::type strategy;
-
- int const side_rj_p = strategy::apply(pi, pj, rj);
- int const side_sj_p = strategy::apply(pi, pj, sj);
+ int const side_rj_p = m_strategy.apply(pi, pj, rj);
+ int const side_sj_p = m_strategy.apply(pi, pj, sj);
// Put the one turning left (1; right == -1) as last
if (side_rj_p != side_sj_p)
@@ -122,8 +126,8 @@ private :
return side_rj_p < side_sj_p;
}
- int const side_sj_r = strategy::apply(ri, rj, sj);
- int const side_rj_s = strategy::apply(si, sj, rj);
+ int const side_sj_r = m_strategy.apply(ri, rj, sj);
+ int const side_rj_s = m_strategy.apply(si, sj, rj);
// If they both turn left: the most left as last
// If they both turn right: this is not relevant, but take also here most left
diff --git a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
index a74bb33ba1..21d079d95c 100644
--- a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
@@ -194,13 +194,15 @@ protected:
typename Turns,
typename LinearGeometry1,
typename LinearGeometry2,
- typename OutputIterator
+ typename OutputIterator,
+ typename IntersectionStrategy
>
static inline OutputIterator
sort_and_follow_turns(Turns& turns,
LinearGeometry1 const& linear1,
LinearGeometry2 const& linear2,
- OutputIterator oit)
+ OutputIterator oit,
+ IntersectionStrategy const& strategy)
{
// remove turns that have no added value
turns::filter_continue_turns
@@ -228,7 +230,7 @@ protected:
FollowIsolatedPoints,
!EnableFilterContinueTurns || OverlayType == overlay_intersection
>::apply(linear1, linear2, boost::begin(turns), boost::end(turns),
- oit);
+ oit, strategy.get_side_strategy());
}
public:
@@ -277,7 +279,7 @@ public:
OverlayType,
EnableFollowIsolatedPoints
&& OverlayType == overlay_intersection
- >(turns, linear1, linear2, oit);
+ >(turns, linear1, linear2, oit, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/overlay/overlay.hpp b/boost/geometry/algorithms/detail/overlay/overlay.hpp
index f1af2f1949..10829abd4f 100644
--- a/boost/geometry/algorithms/detail/overlay/overlay.hpp
+++ b/boost/geometry/algorithms/detail/overlay/overlay.hpp
@@ -28,9 +28,11 @@
#include <boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp>
#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
+#include <boost/geometry/algorithms/detail/overlay/is_self_turn.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
#include <boost/geometry/algorithms/detail/overlay/traverse.hpp>
#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
+#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/algorithms/detail/recalculate.hpp>
@@ -87,29 +89,58 @@ struct overlay_null_visitor
{}
};
-template <typename Turns, typename TurnInfoMap>
-inline void get_ring_turn_info(TurnInfoMap& turn_info_map, Turns const& turns)
+template
+<
+ overlay_type OverlayType,
+ typename TurnInfoMap,
+ typename Turns,
+ typename Clusters
+>
+inline void get_ring_turn_info(TurnInfoMap& turn_info_map, Turns const& turns, Clusters const& clusters)
{
typedef typename boost::range_value<Turns>::type turn_type;
typedef typename turn_type::container_type container_type;
+ static const operation_type target_operation
+ = operation_from_overlay<OverlayType>::value;
+ static const operation_type opposite_operation
+ = target_operation == operation_union ? operation_intersection : operation_union;
+
+ signed_size_type turn_index = 0;
for (typename boost::range_iterator<Turns const>::type
it = boost::begin(turns);
it != boost::end(turns);
- ++it)
+ ++it, turn_index++)
{
- typename boost::range_value<Turns>::type const& turn_info = *it;
-
- if (turn_info.discarded
- && ! turn_info.any_blocked()
- && ! turn_info.colocated)
+ typename boost::range_value<Turns>::type const& turn = *it;
+
+ bool const colocated_target = target_operation == operation_union
+ ? turn.colocated_uu : turn.colocated_ii;
+ bool const colocated_opp = target_operation == operation_union
+ ? turn.colocated_ii : turn.colocated_uu;
+ bool const both_opposite = turn.both(opposite_operation);
+
+ bool const traversed
+ = turn.operations[0].visited.finalized()
+ || turn.operations[0].visited.rejected()
+ || turn.operations[1].visited.finalized()
+ || turn.operations[1].visited.rejected()
+ || turn.both(operation_blocked)
+ || turn.combination(opposite_operation, operation_blocked);
+
+ bool is_closed = false;
+ if (turn.cluster_id >= 0 && target_operation == operation_union)
{
- continue;
+ typename Clusters::const_iterator mit = clusters.find(turn.cluster_id);
+ BOOST_ASSERT(mit != clusters.end());
+
+ cluster_info const& cinfo = mit->second;
+ is_closed = cinfo.open_count == 0;
}
for (typename boost::range_iterator<container_type const>::type
- op_it = boost::begin(turn_info.operations);
- op_it != boost::end(turn_info.operations);
+ op_it = boost::begin(turn.operations);
+ op_it != boost::end(turn.operations);
++op_it)
{
ring_identifier const ring_id
@@ -118,7 +149,34 @@ inline void get_ring_turn_info(TurnInfoMap& turn_info_map, Turns const& turns)
op_it->seg_id.multi_index,
op_it->seg_id.ring_index
);
- turn_info_map[ring_id].has_normal_turn = true;
+
+ if (traversed || is_closed || ! op_it->enriched.startable)
+ {
+ turn_info_map[ring_id].has_traversed_turn = true;
+ }
+ else if (both_opposite && colocated_target)
+ {
+ // For union: ii, colocated with a uu
+ // For example, two interior rings touch where two exterior rings also touch.
+ // The interior rings are not yet traversed, and should be taken from the input
+
+ // For intersection: uu, colocated with an ii
+ // unless it is two interior inner rings colocated with a uu
+
+ // So don't set has_traversed_turn here
+ }
+ else if (both_opposite && ! is_self_turn<OverlayType>(turn))
+ {
+ // For union, mark any ring with a ii turn as traversed
+ // For intersection, any uu - but not if it is a self-turn
+ turn_info_map[ring_id].has_traversed_turn = true;
+ }
+ else if (colocated_opp && ! colocated_target)
+ {
+ // For union, a turn colocated with ii and NOT with uu/ux
+ // For intersection v.v.
+ turn_info_map[ring_id].has_traversed_turn = true;
+ }
}
}
}
@@ -128,18 +186,27 @@ template
<
typename GeometryOut, overlay_type OverlayType, bool ReverseOut,
typename Geometry1, typename Geometry2,
- typename OutputIterator
+ typename OutputIterator, typename Strategy
>
inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1,
Geometry2 const& geometry2,
- OutputIterator out)
+ OutputIterator out, Strategy const& strategy)
{
typedef std::deque
<
typename geometry::ring_type<GeometryOut>::type
> ring_container_type;
- typedef ring_properties<typename geometry::point_type<Geometry1>::type> properties;
+ typedef typename geometry::point_type<Geometry1>::type point_type1;
+
+ typedef ring_properties
+ <
+ point_type1,
+ typename Strategy::template area_strategy
+ <
+ point_type1
+ >::type::return_type
+ > properties;
// Silence warning C4127: conditional expression is constant
#if defined(_MSC_VER)
@@ -164,9 +231,9 @@ inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1,
std::map<ring_identifier, ring_turn_info> empty;
std::map<ring_identifier, properties> all_of_one_of_them;
- select_rings<OverlayType>(geometry1, geometry2, empty, all_of_one_of_them);
+ select_rings<OverlayType>(geometry1, geometry2, empty, all_of_one_of_them, strategy);
ring_container_type rings;
- assign_parents(geometry1, geometry2, rings, all_of_one_of_them);
+ assign_parents(geometry1, geometry2, rings, all_of_one_of_them, strategy);
return add_rings<GeometryOut>(all_of_one_of_them, geometry1, geometry2, rings, out);
}
@@ -201,7 +268,7 @@ struct overlay
return return_if_one_input_is_empty
<
GeometryOut, OverlayType, ReverseOut
- >(geometry1, geometry2, out);
+ >(geometry1, geometry2, out, strategy);
}
typedef typename geometry::point_type<GeometryOut>::type point_type;
@@ -238,10 +305,20 @@ std::cout << "get turns" << std::endl;
visitor.visit_turns(1, turns);
+#ifdef BOOST_GEOMETRY_INCLUDE_SELF_TURNS
+ {
+ self_get_turn_points::self_turns<Reverse1, assign_null_policy>(geometry1,
+ strategy, robust_policy, turns, policy, 0);
+ self_get_turn_points::self_turns<Reverse2, assign_null_policy>(geometry2,
+ strategy, robust_policy, turns, policy, 1);
+ }
+#endif
+
+
#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
std::cout << "enrich" << std::endl;
#endif
- typename Strategy::side_strategy_type side_strategy;
+ typename Strategy::side_strategy_type side_strategy = strategy.get_side_strategy();
cluster_type clusters;
geometry::enrich_intersection_points<Reverse1, Reverse2, OverlayType>(turns,
@@ -271,33 +348,38 @@ std::cout << "traverse" << std::endl;
);
std::map<ring_identifier, ring_turn_info> turn_info_per_ring;
- get_ring_turn_info(turn_info_per_ring, turns);
+ get_ring_turn_info<OverlayType>(turn_info_per_ring, turns, clusters);
+
+ typedef typename Strategy::template area_strategy<point_type>::type area_strategy_type;
typedef ring_properties
- <
- typename geometry::point_type<GeometryOut>::type
- > properties;
+ <
+ point_type,
+ typename area_strategy_type::return_type
+ > properties;
// Select all rings which are NOT touched by any intersection point
std::map<ring_identifier, properties> selected_ring_properties;
select_rings<OverlayType>(geometry1, geometry2, turn_info_per_ring,
- selected_ring_properties);
+ selected_ring_properties, strategy);
// Add rings created during traversal
{
+ area_strategy_type const area_strategy = strategy.template get_area_strategy<point_type>();
+
ring_identifier id(2, 0, -1);
for (typename boost::range_iterator<ring_container_type>::type
it = boost::begin(rings);
it != boost::end(rings);
++it)
{
- selected_ring_properties[id] = properties(*it);
+ selected_ring_properties[id] = properties(*it, area_strategy);
selected_ring_properties[id].reversed = ReverseOut;
id.multi_index++;
}
}
- assign_parents(geometry1, geometry2, rings, selected_ring_properties);
+ assign_parents(geometry1, geometry2, rings, selected_ring_properties, strategy);
return add_rings<GeometryOut>(selected_ring_properties, geometry1, geometry2, rings, out);
}
diff --git a/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp b/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp
index a26f54e008..0a7c3bc469 100644
--- a/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp
+++ b/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp
@@ -1,5 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
+// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
+
// Copyright (c) 2015-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -127,25 +129,57 @@ class multipoint_linear_point
{
private:
// structs for partition -- start
- struct expand_box
+ struct expand_box_point
{
- template <typename Box, typename Geometry>
- static inline void apply(Box& total, Geometry const& geometry)
+ template <typename Box, typename Point>
+ static inline void apply(Box& total, Point const& point)
{
- geometry::expand(total, geometry::return_envelope<Box>(geometry));
+ geometry::expand(total, point);
}
+ };
+
+ template <typename EnvelopeStrategy>
+ struct expand_box_segment
+ {
+ explicit expand_box_segment(EnvelopeStrategy const& strategy)
+ : m_strategy(strategy)
+ {}
+ template <typename Box, typename Segment>
+ inline void apply(Box& total, Segment const& segment) const
+ {
+ geometry::expand(total,
+ geometry::return_envelope<Box>(segment, m_strategy));
+ }
+
+ EnvelopeStrategy const& m_strategy;
};
- struct overlaps_box
+ struct overlaps_box_point
{
- template <typename Box, typename Geometry>
- static inline bool apply(Box const& box, Geometry const& geometry)
+ template <typename Box, typename Point>
+ static inline bool apply(Box const& box, Point const& point)
{
- return ! geometry::disjoint(geometry, box);
+ return ! geometry::disjoint(point, box);
}
};
+ template <typename DisjointStrategy>
+ struct overlaps_box_segment
+ {
+ explicit overlaps_box_segment(DisjointStrategy const& strategy)
+ : m_strategy(strategy)
+ {}
+
+ template <typename Box, typename Segment>
+ inline bool apply(Box const& box, Segment const& segment) const
+ {
+ return ! geometry::disjoint(segment, box, m_strategy);
+ }
+
+ DisjointStrategy const& m_strategy;
+ };
+
template <typename OutputIterator, typename Strategy>
class item_visitor_type
{
@@ -156,12 +190,14 @@ private:
{}
template <typename Item1, typename Item2>
- inline void apply(Item1 const& item1, Item2 const& item2)
+ inline bool apply(Item1 const& item1, Item2 const& item2)
{
action_selector_pl_l
<
PointOut, overlay_intersection
>::apply(item1, Policy::apply(item1, item2, m_strategy), m_oit);
+
+ return true;
}
private:
@@ -202,16 +238,25 @@ private:
{
item_visitor_type<OutputIterator, Strategy> item_visitor(oit, strategy);
- segment_range rng(linear);
+ typedef typename Strategy::envelope_strategy_type envelope_strategy_type;
+ typedef typename Strategy::disjoint_strategy_type disjoint_strategy_type;
+ // TODO: disjoint Segment/Box may be called in partition multiple times
+ // possibly for non-cartesian segments which could be slow. We should consider
+ // passing a range of bounding boxes of segments after calculating them once.
+ // Alternatively instead of a range of segments a range of Segment/Envelope pairs
+ // should be passed, where envelope would be lazily calculated when needed the first time
geometry::partition
<
geometry::model::box
<
typename boost::range_value<MultiPoint>::type
>
- >::apply(multipoint, rng, item_visitor,
- expand_box(), overlaps_box());
+ >::apply(multipoint, segment_range(linear), item_visitor,
+ expand_box_point(),
+ overlaps_box_point(),
+ expand_box_segment<envelope_strategy_type>(strategy.get_envelope_strategy()),
+ overlaps_box_segment<disjoint_strategy_type>(strategy.get_disjoint_strategy()));
return oit;
}
diff --git a/boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp b/boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp
new file mode 100644
index 0000000000..d4a47abecf
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp
@@ -0,0 +1,178 @@
+// Boost.Geometry
+
+// Copyright (c) 2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the 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_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_RANGE_IN_GEOMETRY_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_RANGE_IN_GEOMETRY_HPP
+
+
+#include <boost/geometry/algorithms/covered_by.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/iterators/point_iterator.hpp>
+
+#include <boost/range.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+template
+<
+ typename Geometry,
+ typename Tag = typename geometry::tag<Geometry>::type
+>
+struct points_range
+{
+ typedef geometry::point_iterator<Geometry const> iterator_type;
+
+ explicit points_range(Geometry const& geometry)
+ : m_geometry(geometry)
+ {}
+
+ iterator_type begin() const
+ {
+ return geometry::points_begin(m_geometry);
+ }
+
+ iterator_type end() const
+ {
+ return geometry::points_end(m_geometry);
+ }
+
+ Geometry const& m_geometry;
+};
+// Specialized because point_iterator doesn't support boxes
+template <typename Box>
+struct points_range<Box, box_tag>
+{
+ typedef typename geometry::point_type<Box>::type point_type;
+ typedef const point_type * iterator_type;
+
+ explicit points_range(Box const& box)
+ {
+ detail::assign_box_corners(box,
+ m_corners[0], m_corners[1], m_corners[2], m_corners[3]);
+ }
+
+ iterator_type begin() const
+ {
+ return m_corners;
+ }
+
+ iterator_type end() const
+ {
+ return m_corners + 4;
+ }
+
+ point_type m_corners[4];
+};
+
+template
+<
+ typename Geometry,
+ typename Tag = typename geometry::tag<Geometry>::type
+>
+struct point_in_geometry_helper
+{
+ template <typename Point, typename Strategy>
+ static inline int apply(Point const& point, Geometry const& geometry,
+ Strategy const& strategy)
+ {
+ return detail::within::point_in_geometry(point, geometry, strategy);
+ }
+};
+// Specialized because point_in_geometry doesn't support Boxes
+template <typename Box>
+struct point_in_geometry_helper<Box, box_tag>
+{
+ template <typename Point, typename Strategy>
+ static inline int apply(Point const& point, Box const& box,
+ Strategy const&)
+ {
+ return geometry::covered_by(point, box) ? 1 : -1;
+ }
+};
+
+// This function returns
+// when it finds a point of geometry1 inside or outside geometry2
+template <typename Geometry1, typename Geometry2, typename Strategy>
+static inline int range_in_geometry(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy,
+ bool skip_first = false)
+{
+ int result = 0;
+ points_range<Geometry1> points(geometry1);
+ typedef typename points_range<Geometry1>::iterator_type iterator_type;
+ iterator_type const end = points.end();
+ iterator_type it = points.begin();
+ if (it == end)
+ {
+ return result;
+ }
+ else if (skip_first)
+ {
+ ++it;
+ }
+
+ typename Strategy::template point_in_geometry_strategy
+ <
+ Geometry1, Geometry2
+ >::type const in_strategy
+ = strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>();
+
+ for ( ; it != end; ++it)
+ {
+ result = point_in_geometry_helper<Geometry2>::apply(*it, geometry2, in_strategy);
+ if (result != 0)
+ {
+ return result;
+ }
+ }
+ // all points contained entirely by the boundary
+ return result;
+}
+
+// This function returns if first_point1 is inside or outside geometry2 or
+// when it finds a point of geometry1 inside or outside geometry2
+template <typename Point1, typename Geometry1, typename Geometry2, typename Strategy>
+inline int range_in_geometry(Point1 const& first_point1,
+ Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ // check a point on border of geometry1 first
+ int result = point_in_geometry_helper<Geometry2>::apply(first_point1, geometry2,
+ strategy.template get_point_in_geometry_strategy<Point1, Geometry2>());
+ if (result == 0)
+ {
+ // if a point is on boundary of geometry2
+ // check points of geometry1 until point inside/outside is found
+ // NOTE: skip first point because it should be already tested above
+ result = range_in_geometry(geometry1, geometry2, strategy, true);
+ }
+ return result;
+}
+
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_RANGE_IN_GEOMETRY_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/ring_properties.hpp b/boost/geometry/algorithms/detail/overlay/ring_properties.hpp
index 0f2da67b62..7dbc5d5fab 100644
--- a/boost/geometry/algorithms/detail/overlay/ring_properties.hpp
+++ b/boost/geometry/algorithms/detail/overlay/ring_properties.hpp
@@ -2,6 +2,10 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -23,11 +27,11 @@ namespace boost { namespace geometry
namespace detail { namespace overlay
{
-template <typename Point>
+template <typename Point, typename AreaType>
struct ring_properties
{
typedef Point point_type;
- typedef typename default_area_result<Point>::type area_type;
+ typedef AreaType area_type;
bool valid;
@@ -52,17 +56,14 @@ struct ring_properties
, parent_area(-1)
{}
- template <typename RingOrBox>
- inline ring_properties(RingOrBox const& ring_or_box)
+ template <typename RingOrBox, typename AreaStrategy>
+ inline ring_properties(RingOrBox const& ring_or_box, AreaStrategy const& strategy)
: reversed(false)
, discarded(false)
, parent_area(-1)
{
- this->area = geometry::area(ring_or_box);
- // We should take a point somewhere in the middle of the ring,
- // to avoid taking a point on a (self)tangency,
- // in cases where multiple points come together
- valid = geometry::point_on_border(this->point, ring_or_box, true);
+ this->area = geometry::area(ring_or_box, strategy);
+ valid = geometry::point_on_border(this->point, ring_or_box);
}
inline area_type get_area() const
diff --git a/boost/geometry/algorithms/detail/overlay/select_rings.hpp b/boost/geometry/algorithms/detail/overlay/select_rings.hpp
index de5eac8acb..67a4f4bb75 100644
--- a/boost/geometry/algorithms/detail/overlay/select_rings.hpp
+++ b/boost/geometry/algorithms/detail/overlay/select_rings.hpp
@@ -3,6 +3,10 @@
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -18,9 +22,10 @@
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/area.hpp>
-#include <boost/geometry/algorithms/within.hpp>
+#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
+#include <boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp>
#include <boost/geometry/algorithms/detail/overlay/ring_properties.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
@@ -35,11 +40,11 @@ namespace detail { namespace overlay
struct ring_turn_info
{
- bool has_normal_turn;
+ bool has_traversed_turn;
bool within_other;
ring_turn_info()
- : has_normal_turn(false)
+ : has_traversed_turn(false)
, within_other(false)
{}
};
@@ -54,41 +59,45 @@ namespace dispatch
template <typename Box>
struct select_rings<box_tag, Box>
{
- template <typename Geometry, typename RingPropertyMap>
+ template <typename Geometry, typename RingPropertyMap, typename AreaStrategy>
static inline void apply(Box const& box, Geometry const& ,
- ring_identifier const& id, RingPropertyMap& ring_properties)
+ ring_identifier const& id, RingPropertyMap& ring_properties,
+ AreaStrategy const& strategy)
{
- ring_properties[id] = typename RingPropertyMap::mapped_type(box);
+ ring_properties[id] = typename RingPropertyMap::mapped_type(box, strategy);
}
- template <typename RingPropertyMap>
+ template <typename RingPropertyMap, typename AreaStrategy>
static inline void apply(Box const& box,
- ring_identifier const& id, RingPropertyMap& ring_properties)
+ ring_identifier const& id, RingPropertyMap& ring_properties,
+ AreaStrategy const& strategy)
{
- ring_properties[id] = typename RingPropertyMap::mapped_type(box);
+ ring_properties[id] = typename RingPropertyMap::mapped_type(box, strategy);
}
};
template <typename Ring>
struct select_rings<ring_tag, Ring>
{
- template <typename Geometry, typename RingPropertyMap>
+ template <typename Geometry, typename RingPropertyMap, typename AreaStrategy>
static inline void apply(Ring const& ring, Geometry const& ,
- ring_identifier const& id, RingPropertyMap& ring_properties)
+ ring_identifier const& id, RingPropertyMap& ring_properties,
+ AreaStrategy const& strategy)
{
if (boost::size(ring) > 0)
{
- ring_properties[id] = typename RingPropertyMap::mapped_type(ring);
+ ring_properties[id] = typename RingPropertyMap::mapped_type(ring, strategy);
}
}
- template <typename RingPropertyMap>
+ template <typename RingPropertyMap, typename AreaStrategy>
static inline void apply(Ring const& ring,
- ring_identifier const& id, RingPropertyMap& ring_properties)
+ ring_identifier const& id, RingPropertyMap& ring_properties,
+ AreaStrategy const& strategy)
{
if (boost::size(ring) > 0)
{
- ring_properties[id] = typename RingPropertyMap::mapped_type(ring);
+ ring_properties[id] = typename RingPropertyMap::mapped_type(ring, strategy);
}
}
};
@@ -97,14 +106,15 @@ namespace dispatch
template <typename Polygon>
struct select_rings<polygon_tag, Polygon>
{
- template <typename Geometry, typename RingPropertyMap>
+ template <typename Geometry, typename RingPropertyMap, typename AreaStrategy>
static inline void apply(Polygon const& polygon, Geometry const& geometry,
- ring_identifier id, RingPropertyMap& ring_properties)
+ ring_identifier id, RingPropertyMap& ring_properties,
+ AreaStrategy const& strategy)
{
typedef typename geometry::ring_type<Polygon>::type ring_type;
typedef select_rings<ring_tag, ring_type> per_ring;
- per_ring::apply(exterior_ring(polygon), geometry, id, ring_properties);
+ per_ring::apply(exterior_ring(polygon), geometry, id, ring_properties, strategy);
typename interior_return_type<Polygon const>::type
rings = interior_rings(polygon);
@@ -112,18 +122,19 @@ namespace dispatch
it = boost::begin(rings); it != boost::end(rings); ++it)
{
id.ring_index++;
- per_ring::apply(*it, geometry, id, ring_properties);
+ per_ring::apply(*it, geometry, id, ring_properties, strategy);
}
}
- template <typename RingPropertyMap>
+ template <typename RingPropertyMap, typename AreaStrategy>
static inline void apply(Polygon const& polygon,
- ring_identifier id, RingPropertyMap& ring_properties)
+ ring_identifier id, RingPropertyMap& ring_properties,
+ AreaStrategy const& strategy)
{
typedef typename geometry::ring_type<Polygon>::type ring_type;
typedef select_rings<ring_tag, ring_type> per_ring;
- per_ring::apply(exterior_ring(polygon), id, ring_properties);
+ per_ring::apply(exterior_ring(polygon), id, ring_properties, strategy);
typename interior_return_type<Polygon const>::type
rings = interior_rings(polygon);
@@ -131,7 +142,7 @@ namespace dispatch
it = boost::begin(rings); it != boost::end(rings); ++it)
{
id.ring_index++;
- per_ring::apply(*it, id, ring_properties);
+ per_ring::apply(*it, id, ring_properties, strategy);
}
}
};
@@ -139,9 +150,10 @@ namespace dispatch
template <typename Multi>
struct select_rings<multi_polygon_tag, Multi>
{
- template <typename Geometry, typename RingPropertyMap>
+ template <typename Geometry, typename RingPropertyMap, typename AreaStrategy>
static inline void apply(Multi const& multi, Geometry const& geometry,
- ring_identifier id, RingPropertyMap& ring_properties)
+ ring_identifier id, RingPropertyMap& ring_properties,
+ AreaStrategy const& strategy)
{
typedef typename boost::range_iterator
<
@@ -154,7 +166,7 @@ namespace dispatch
for (iterator_type it = boost::begin(multi); it != boost::end(multi); ++it)
{
id.ring_index = -1;
- per_polygon::apply(*it, geometry, id, ring_properties);
+ per_polygon::apply(*it, geometry, id, ring_properties, strategy);
id.multi_index++;
}
}
@@ -221,20 +233,21 @@ struct decide<overlay_intersection>
}
};
-
template
<
overlay_type OverlayType,
typename Geometry1,
typename Geometry2,
typename TurnInfoMap,
- typename RingPropertyMap
+ typename RingPropertyMap,
+ typename Strategy
>
inline void update_ring_selection(Geometry1 const& geometry1,
Geometry2 const& geometry2,
TurnInfoMap const& turn_info_map,
RingPropertyMap const& all_ring_properties,
- RingPropertyMap& selected_ring_properties)
+ RingPropertyMap& selected_ring_properties,
+ Strategy const& strategy)
{
selected_ring_properties.clear();
@@ -252,9 +265,9 @@ inline void update_ring_selection(Geometry1 const& geometry1,
info = tcit->second; // Copy by value
}
- if (info.has_normal_turn)
+ if (info.has_traversed_turn)
{
- // There are normal turns on this ring. It should be traversed, we
+ // This turn is traversed (or blocked),
// don't include the original ring
continue;
}
@@ -263,11 +276,16 @@ inline void update_ring_selection(Geometry1 const& geometry1,
// a point lying on the ring
switch(id.source_index)
{
+ // within
case 0 :
- info.within_other = geometry::within(it->second.point, geometry2);
+ info.within_other = range_in_geometry(it->second.point,
+ geometry1, geometry2,
+ strategy) > 0;
break;
case 1 :
- info.within_other = geometry::within(it->second.point, geometry1);
+ info.within_other = range_in_geometry(it->second.point,
+ geometry2, geometry1,
+ strategy) > 0;
break;
}
@@ -290,23 +308,30 @@ template
typename Geometry1,
typename Geometry2,
typename RingTurnInfoMap,
- typename RingPropertyMap
+ typename RingPropertyMap,
+ typename Strategy
>
inline void select_rings(Geometry1 const& geometry1, Geometry2 const& geometry2,
RingTurnInfoMap const& turn_info_per_ring,
- RingPropertyMap& selected_ring_properties)
+ RingPropertyMap& selected_ring_properties,
+ Strategy const& strategy)
{
typedef typename geometry::tag<Geometry1>::type tag1;
typedef typename geometry::tag<Geometry2>::type tag2;
+ typedef typename geometry::point_type<Geometry1>::type point1_type;
+ typedef typename geometry::point_type<Geometry2>::type point2_type;
RingPropertyMap all_ring_properties;
dispatch::select_rings<tag1, Geometry1>::apply(geometry1, geometry2,
- ring_identifier(0, -1, -1), all_ring_properties);
+ ring_identifier(0, -1, -1), all_ring_properties,
+ strategy.template get_area_strategy<point1_type>());
dispatch::select_rings<tag2, Geometry2>::apply(geometry2, geometry1,
- ring_identifier(1, -1, -1), all_ring_properties);
+ ring_identifier(1, -1, -1), all_ring_properties,
+ strategy.template get_area_strategy<point2_type>());
update_ring_selection<OverlayType>(geometry1, geometry2, turn_info_per_ring,
- all_ring_properties, selected_ring_properties);
+ all_ring_properties, selected_ring_properties,
+ strategy);
}
template
@@ -314,20 +339,25 @@ template
overlay_type OverlayType,
typename Geometry,
typename RingTurnInfoMap,
- typename RingPropertyMap
+ typename RingPropertyMap,
+ typename Strategy
>
inline void select_rings(Geometry const& geometry,
RingTurnInfoMap const& turn_info_per_ring,
- RingPropertyMap& selected_ring_properties)
+ RingPropertyMap& selected_ring_properties,
+ Strategy const& strategy)
{
typedef typename geometry::tag<Geometry>::type tag;
+ typedef typename geometry::point_type<Geometry>::type point_type;
RingPropertyMap all_ring_properties;
dispatch::select_rings<tag, Geometry>::apply(geometry,
- ring_identifier(0, -1, -1), all_ring_properties);
+ ring_identifier(0, -1, -1), all_ring_properties,
+ strategy.template get_area_strategy<point_type>());
update_ring_selection<OverlayType>(geometry, geometry, turn_info_per_ring,
- all_ring_properties, selected_ring_properties);
+ all_ring_properties, selected_ring_properties,
+ strategy);
}
diff --git a/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp b/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
index 8540ef98a0..5e9d8efa8e 100644
--- a/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
+++ b/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
@@ -22,12 +23,14 @@
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
#include <boost/geometry/algorithms/detail/partition.hpp>
+#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
#include <boost/geometry/algorithms/detail/sections/section_box_policies.hpp>
@@ -57,12 +60,9 @@ struct no_interrupt_policy
};
-
-
-class self_ip_exception : public geometry::exception {};
-
template
<
+ bool Reverse,
typename Geometry,
typename Turns,
typename TurnPolicy,
@@ -77,17 +77,20 @@ struct self_section_visitor
RobustPolicy const& m_rescale_policy;
Turns& m_turns;
InterruptPolicy& m_interrupt_policy;
+ std::size_t m_source_index;
inline self_section_visitor(Geometry const& g,
IntersectionStrategy const& is,
RobustPolicy const& rp,
Turns& turns,
- InterruptPolicy& ip)
+ InterruptPolicy& ip,
+ std::size_t source_index)
: m_geometry(g)
, m_intersection_strategy(is)
, m_rescale_policy(rp)
, m_turns(turns)
, m_interrupt_policy(ip)
+ , m_source_index(source_index)
{}
template <typename Section>
@@ -97,26 +100,21 @@ struct self_section_visitor
&& ! sec1.duplicate
&& ! sec2.duplicate)
{
- detail::get_turns::get_turns_in_sections
+ // false if interrupted
+ return detail::get_turns::get_turns_in_sections
<
Geometry, Geometry,
- false, false,
+ Reverse, Reverse,
Section, Section,
TurnPolicy
- >::apply(
- 0, m_geometry, sec1,
- 0, m_geometry, sec2,
- false,
- m_intersection_strategy,
- m_rescale_policy,
- m_turns, m_interrupt_policy);
- }
- if (BOOST_GEOMETRY_CONDITION(m_interrupt_policy.has_intersections))
- {
- // TODO: we should give partition an interrupt policy.
- // Now we throw, and catch below, to stop the partition loop.
- throw self_ip_exception();
+ >::apply(m_source_index, m_geometry, sec1,
+ m_source_index, m_geometry, sec2,
+ false,
+ m_intersection_strategy,
+ m_rescale_policy,
+ m_turns, m_interrupt_policy);
}
+
return true;
}
@@ -124,7 +122,7 @@ struct self_section_visitor
-template<typename TurnPolicy>
+template <bool Reverse, typename TurnPolicy>
struct get_turns
{
template <typename Geometry, typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
@@ -133,7 +131,8 @@ struct get_turns
IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
Turns& turns,
- InterruptPolicy& interrupt_policy)
+ InterruptPolicy& interrupt_policy,
+ std::size_t source_index)
{
typedef model::box
<
@@ -149,29 +148,24 @@ struct get_turns
typedef boost::mpl::vector_c<std::size_t, 0> dimensions;
sections_type sec;
- geometry::sectionalize<false, dimensions>(geometry, robust_policy, sec);
+ geometry::sectionalize<Reverse, dimensions>(geometry, robust_policy, sec,
+ intersection_strategy.get_envelope_strategy());
self_section_visitor
<
- Geometry,
+ Reverse, Geometry,
Turns, TurnPolicy, IntersectionStrategy, RobustPolicy, InterruptPolicy
- > visitor(geometry, intersection_strategy, robust_policy, turns, interrupt_policy);
+ > visitor(geometry, intersection_strategy, robust_policy, turns, interrupt_policy, source_index);
- try
- {
- geometry::partition
- <
- box_type
- >::apply(sec, visitor,
- detail::section::get_section_box(),
- detail::section::overlaps_section_box());
- }
- catch(self_ip_exception const& )
- {
- return false;
- }
+ // false if interrupted
+ geometry::partition
+ <
+ box_type
+ >::apply(sec, visitor,
+ detail::section::get_section_box(),
+ detail::section::overlaps_section_box());
- return true;
+ return ! interrupt_policy.has_intersections;
}
};
@@ -186,6 +180,7 @@ namespace dispatch
template
<
+ bool Reverse,
typename GeometryTag,
typename Geometry,
typename TurnPolicy
@@ -197,26 +192,28 @@ struct self_get_turn_points
template
<
+ bool Reverse,
typename Ring,
typename TurnPolicy
>
struct self_get_turn_points
<
- ring_tag, Ring,
+ Reverse, ring_tag, Ring,
TurnPolicy
>
- : detail::self_get_turn_points::get_turns<TurnPolicy>
+ : detail::self_get_turn_points::get_turns<Reverse, TurnPolicy>
{};
template
<
+ bool Reverse,
typename Box,
typename TurnPolicy
>
struct self_get_turn_points
<
- box_tag, Box,
+ Reverse, box_tag, Box,
TurnPolicy
>
{
@@ -226,7 +223,8 @@ struct self_get_turn_points
Strategy const& ,
RobustPolicy const& ,
Turns& ,
- InterruptPolicy& )
+ InterruptPolicy& ,
+ std::size_t)
{
return true;
}
@@ -235,29 +233,31 @@ struct self_get_turn_points
template
<
+ bool Reverse,
typename Polygon,
typename TurnPolicy
>
struct self_get_turn_points
<
- polygon_tag, Polygon,
+ Reverse, polygon_tag, Polygon,
TurnPolicy
>
- : detail::self_get_turn_points::get_turns<TurnPolicy>
+ : detail::self_get_turn_points::get_turns<Reverse, TurnPolicy>
{};
template
<
+ bool Reverse,
typename MultiPolygon,
typename TurnPolicy
>
struct self_get_turn_points
<
- multi_polygon_tag, MultiPolygon,
+ Reverse, multi_polygon_tag, MultiPolygon,
TurnPolicy
>
- : detail::self_get_turn_points::get_turns<TurnPolicy>
+ : detail::self_get_turn_points::get_turns<Reverse, TurnPolicy>
{};
@@ -265,6 +265,45 @@ struct self_get_turn_points
#endif // DOXYGEN_NO_DISPATCH
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace self_get_turn_points
+{
+
+// Version where Reverse can be specified manually. TODO:
+// can most probably be merged with self_get_turn_points::get_turn
+template
+<
+ bool Reverse,
+ typename AssignPolicy,
+ typename Geometry,
+ typename IntersectionStrategy,
+ typename RobustPolicy,
+ typename Turns,
+ typename InterruptPolicy
+>
+inline void self_turns(Geometry const& geometry,
+ IntersectionStrategy const& strategy,
+ RobustPolicy const& robust_policy,
+ Turns& turns,
+ InterruptPolicy& interrupt_policy,
+ std::size_t source_index = 0)
+{
+ concepts::check<Geometry const>();
+
+ typedef detail::overlay::get_turn_info<detail::overlay::assign_null_policy> turn_policy;
+
+ dispatch::self_get_turn_points
+ <
+ Reverse,
+ typename tag<Geometry>::type,
+ Geometry,
+ turn_policy
+ >::apply(geometry, strategy, robust_policy, turns, interrupt_policy, source_index);
+}
+
+}} // namespace detail::self_get_turn_points
+#endif // DOXYGEN_NO_DETAIL
+
/*!
\brief Calculate self intersections of a geometry
\ingroup overlay
@@ -290,18 +329,22 @@ template
inline void self_turns(Geometry const& geometry,
IntersectionStrategy const& strategy,
RobustPolicy const& robust_policy,
- Turns& turns, InterruptPolicy& interrupt_policy)
+ Turns& turns,
+ InterruptPolicy& interrupt_policy,
+ std::size_t source_index = 0)
{
concepts::check<Geometry const>();
- typedef detail::overlay::get_turn_info<detail::overlay::assign_null_policy> turn_policy;
+ static bool const reverse = detail::overlay::do_reverse
+ <
+ geometry::point_order<Geometry>::value
+ >::value;
- dispatch::self_get_turn_points
+ detail::self_get_turn_points::self_turns
<
- typename tag<Geometry>::type,
- Geometry,
- turn_policy
- >::apply(geometry, strategy, robust_policy, turns, interrupt_policy);
+ reverse,
+ AssignPolicy
+ >(geometry, strategy, robust_policy, turns, interrupt_policy, source_index);
}
diff --git a/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp b/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp
index bbba623eee..5ad2e41b12 100644
--- a/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp
+++ b/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp
@@ -2,6 +2,11 @@
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -10,11 +15,14 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SORT_BY_SIDE_HPP
#include <algorithm>
+#include <map>
#include <vector>
+#include <boost/geometry/algorithms/num_points.hpp>
+#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>
+#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
#include <boost/geometry/algorithms/detail/direction_code.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
-#include <boost/geometry/strategies/side.hpp>
namespace boost { namespace geometry
{
@@ -37,7 +45,6 @@ struct ranked_point
, count_left(0)
, count_right(0)
, operation(operation_none)
- , only_turn_on_ring(false)
{}
template <typename Op>
@@ -53,7 +60,6 @@ struct ranked_point
, count_right(0)
, operation(op.operation)
, seg_id(op.seg_id)
- , only_turn_on_ring(op.enriched.only_turn_on_ring)
{}
Point point;
@@ -66,7 +72,6 @@ struct ranked_point
std::size_t count_right;
operation_type operation;
segment_identifier seg_id;
- bool only_turn_on_ring;
};
struct less_by_turn_index
@@ -105,17 +110,13 @@ struct less_false
}
};
-template <typename Point, typename LessOnSame, typename Compare>
+template <typename Point, typename SideStrategy, typename LessOnSame, typename Compare>
struct less_by_side
{
- typedef typename strategy::side::services::default_strategy
- <
- typename cs_tag<Point>::type
- >::type side;
-
- less_by_side(const Point& p1, const Point& p2)
+ less_by_side(const Point& p1, const Point& p2, SideStrategy const& strategy)
: m_p1(p1)
, m_p2(p2)
+ , m_strategy(strategy)
{}
template <typename T>
@@ -124,8 +125,8 @@ struct less_by_side
LessOnSame on_same;
Compare compare;
- int const side_first = side::apply(m_p1, m_p2, first.point);
- int const side_second = side::apply(m_p1, m_p2, second.point);
+ int const side_first = m_strategy.apply(m_p1, m_p2, first.point);
+ int const side_second = m_strategy.apply(m_p1, m_p2, second.point);
if (side_first == 0 && side_second == 0)
{
@@ -165,7 +166,7 @@ struct less_by_side
// They are both left, both right, and/or both collinear (with each other and/or with p1,p2)
// Check mutual side
- int const side_second_wrt_first = side::apply(m_p2, first.point, second.point);
+ int const side_second_wrt_first = m_strategy.apply(m_p2, first.point, second.point);
if (side_second_wrt_first == 0)
{
@@ -183,10 +184,19 @@ struct less_by_side
private :
Point m_p1, m_p2;
+ SideStrategy const& m_strategy;
};
// Sorts vectors in counter clockwise order (by default)
-template <bool Reverse1, bool Reverse2, typename Point, typename Compare>
+template
+<
+ bool Reverse1,
+ bool Reverse2,
+ overlay_type OverlayType,
+ typename Point,
+ typename SideStrategy,
+ typename Compare
+>
struct side_sorter
{
typedef ranked_point<Point> rp;
@@ -215,13 +225,14 @@ private :
};
public :
- inline void set_origin(Point const& origin)
- {
- m_origin = origin;
- }
+ side_sorter(SideStrategy const& strategy)
+ : m_origin_count(0)
+ , m_origin_segment_distance(0)
+ , m_strategy(strategy)
+ {}
template <typename Operation, typename Geometry1, typename Geometry2>
- void add(Operation const& op, signed_size_type turn_index, signed_size_type op_index,
+ Point add(Operation const& op, signed_size_type turn_index, signed_size_type op_index,
Geometry1 const& geometry1,
Geometry2 const& geometry2,
bool is_origin)
@@ -233,11 +244,63 @@ public :
m_ranked_points.push_back(rp(point1, turn_index, op_index, dir_from, op));
m_ranked_points.push_back(rp(point_to, turn_index, op_index, dir_to, op));
-
if (is_origin)
{
m_origin = point1;
+ m_origin_count++;
}
+ return point1;
+ }
+
+ template <typename Operation, typename Geometry1, typename Geometry2>
+ void add(Operation const& op, signed_size_type turn_index, signed_size_type op_index,
+ segment_identifier const& departure_seg_id,
+ Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ bool check_origin)
+ {
+ Point const point1 = add(op, turn_index, op_index, geometry1, geometry2, false);
+
+ if (check_origin)
+ {
+ bool const is_origin
+ = op.seg_id.source_index == departure_seg_id.source_index
+ && op.seg_id.ring_index == departure_seg_id.ring_index
+ && op.seg_id.multi_index == departure_seg_id.multi_index;
+
+ if (is_origin)
+ {
+ int const segment_distance = calculate_segment_distance(op, departure_seg_id, geometry1, geometry2);
+ if (m_origin_count == 0 ||
+ segment_distance < m_origin_segment_distance)
+ {
+ m_origin = point1;
+ m_origin_segment_distance = segment_distance;
+ }
+ m_origin_count++;
+ }
+ }
+ }
+
+ template <typename Operation, typename Geometry1, typename Geometry2>
+ static int calculate_segment_distance(Operation const& op,
+ segment_identifier const& departure_seg_id,
+ Geometry1 const& geometry1,
+ Geometry2 const& geometry2)
+ {
+ if (op.seg_id.segment_index >= departure_seg_id.segment_index)
+ {
+ return op.seg_id.segment_index - departure_seg_id.segment_index;
+ }
+ // Take wrap into account
+ // Suppose ring_count=10 (10 points, 9 segments), dep.seg_id=7, op.seg_id=2, then distance=10-9+2
+ // Generic function (is this used somewhere else too?)
+ ring_identifier const rid(op.seg_id.source_index, op.seg_id.multi_index, op.seg_id.ring_index);
+ int const segment_count
+ (op.seg_id.source_index == 0
+ ? geometry::num_points(detail::overlay::get_ring<typename geometry::tag<Geometry1>::type>::apply(rid, geometry1))
+ : geometry::num_points(detail::overlay::get_ring<typename geometry::tag<Geometry2>::type>::apply(rid, geometry2)));
+ return ((segment_count - 1) - departure_seg_id.segment_index) + op.seg_id.segment_index;
}
void apply(Point const& turn_point)
@@ -249,8 +312,8 @@ public :
// to give colinear points
// Sort by side and assign rank
- less_by_side<Point, less_by_index, Compare> less_unique(m_origin, turn_point);
- less_by_side<Point, less_false, Compare> less_non_unique(m_origin, turn_point);
+ less_by_side<Point, SideStrategy, less_by_index, Compare> less_unique(m_origin, turn_point, m_strategy);
+ less_by_side<Point, SideStrategy, less_false, Compare> less_non_unique(m_origin, turn_point, m_strategy);
std::sort(m_ranked_points.begin(), m_ranked_points.end(), less_unique);
@@ -269,7 +332,7 @@ public :
}
template <signed_size_type segment_identifier::*Member, typename Map>
- void find_open_generic(Map& handled)
+ void find_open_generic(Map& handled, bool check)
{
for (std::size_t i = 0; i < m_ranked_points.size(); i++)
{
@@ -280,6 +343,11 @@ public :
}
signed_size_type const& index = ranked.seg_id.*Member;
+ if (check && (index < 0 || index > 1))
+ {
+ // Should not occur
+ continue;
+ }
if (! handled[index])
{
find_polygons_for_source<Member>(index, i);
@@ -290,36 +358,23 @@ public :
void find_open()
{
- // TODO: we might pass Buffer as overlay_type, instead on the fly below
- bool one_source = true;
- for (std::size_t i = 0; i < m_ranked_points.size(); i++)
- {
- const rp& ranked = m_ranked_points[i];
- signed_size_type const& src = ranked.seg_id.source_index;
- if (src != 0)
- {
- one_source = false;
- break;
- }
- }
-
- if (one_source)
+ if (OverlayType == overlay_buffer)
{
- // by multi index
+ // For buffers, use piece index
std::map<signed_size_type, bool> handled;
find_open_generic
<
&segment_identifier::piece_index
- >(handled);
+ >(handled, false);
}
else
{
- // by source (there should only source 0,1) TODO assert this
+ // For other operations, by source (there should only source 0,1)
bool handled[2] = {false, false};
find_open_generic
<
&segment_identifier::source_index
- >(handled);
+ >(handled, true);
}
}
@@ -361,11 +416,19 @@ public :
}
}
+ bool has_origin() const
+ {
+ return m_origin_count > 0;
+ }
+
//private :
typedef std::vector<rp> container_type;
container_type m_ranked_points;
Point m_origin;
+ std::size_t m_origin_count;
+ int m_origin_segment_distance;
+ SideStrategy m_strategy;
private :
@@ -439,9 +502,10 @@ private :
void find_polygons_for_source(signed_size_type the_index,
std::size_t start_index)
{
- int state = 1; // 'closed', because start_index is "from", arrives at the turn
- std::size_t last_from_rank = m_ranked_points[start_index].rank;
- std::size_t previous_rank = m_ranked_points[start_index].rank;
+ bool in_polygon = true; // Because start_index is "from", arrives at the turn
+ rp const& start_rp = m_ranked_points[start_index];
+ std::size_t last_from_rank = start_rp.rank;
+ std::size_t previous_rank = start_rp.rank;
for (std::size_t index = move<Member>(the_index, start_index);
;
@@ -449,7 +513,7 @@ private :
{
rp& ranked = m_ranked_points[index];
- if (ranked.rank != previous_rank && state == 0)
+ if (ranked.rank != previous_rank && ! in_polygon)
{
assign_ranks(last_from_rank, previous_rank - 1, 1);
assign_ranks(last_from_rank + 1, previous_rank, 2);
@@ -463,11 +527,11 @@ private :
if (ranked.direction == dir_from)
{
last_from_rank = ranked.rank;
- state++;
+ in_polygon = true;
}
else if (ranked.direction == dir_to)
{
- state--;
+ in_polygon = false;
}
previous_rank = ranked.rank;
diff --git a/boost/geometry/algorithms/detail/overlay/traversal.hpp b/boost/geometry/algorithms/detail/overlay/traversal.hpp
index bc828920e9..69d62b788b 100644
--- a/boost/geometry/algorithms/detail/overlay/traversal.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traversal.hpp
@@ -2,6 +2,11 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -14,7 +19,9 @@
#include <boost/range.hpp>
#include <boost/geometry/algorithms/detail/overlay/aggregate_operations.hpp>
+#include <boost/geometry/algorithms/detail/overlay/is_self_turn.hpp>
#include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>
+#include <boost/geometry/algorithms/detail/overlay/traversal_intersection_patterns.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/assert.hpp>
@@ -37,9 +44,13 @@ namespace detail { namespace overlay
template <typename Turn, typename Operation>
#ifdef BOOST_GEOMETRY_DEBUG_TRAVERSE
inline void debug_traverse(Turn const& turn, Operation op,
- std::string const& header)
+ std::string const& header, bool condition = true)
{
- std::cout << header
+ if (! condition)
+ {
+ return;
+ }
+ std::cout << " " << header
<< " at " << op.seg_id
<< " meth: " << method_char(turn.method)
<< " op: " << operation_char(op.operation)
@@ -55,7 +66,7 @@ inline void debug_traverse(Turn const& turn, Operation op,
}
}
#else
-inline void debug_traverse(Turn const& , Operation, const char*)
+inline void debug_traverse(Turn const& , Operation, const char*, bool = true)
{
}
#endif
@@ -88,6 +99,7 @@ template
typename Turns,
typename Clusters,
typename RobustPolicy,
+ typename SideStrategy,
typename Visitor
>
struct traversal
@@ -101,18 +113,20 @@ struct traversal
typedef typename geometry::point_type<Geometry1>::type point_type;
typedef sort_by_side::side_sorter
<
- Reverse1, Reverse2,
- point_type, side_compare_type
+ Reverse1, Reverse2, OverlayType,
+ point_type, SideStrategy, side_compare_type
> sbs_type;
inline traversal(Geometry1 const& geometry1, Geometry2 const& geometry2,
Turns& turns, Clusters const& clusters,
- RobustPolicy const& robust_policy, Visitor& visitor)
+ RobustPolicy const& robust_policy, SideStrategy const& strategy,
+ Visitor& visitor)
: m_geometry1(geometry1)
, m_geometry2(geometry2)
, m_turns(turns)
, m_clusters(clusters)
, m_robust_policy(robust_policy)
+ , m_strategy(strategy)
, m_visitor(visitor)
{
}
@@ -133,11 +147,38 @@ struct traversal
}
}
+ //! Sets visited for ALL turns traveling to the same turn
+ inline void set_visited_in_cluster(signed_size_type cluster_id,
+ signed_size_type rank)
+ {
+ typename Clusters::const_iterator mit = m_clusters.find(cluster_id);
+ BOOST_ASSERT(mit != m_clusters.end());
+
+ cluster_info const& cinfo = mit->second;
+ std::set<signed_size_type> const& ids = cinfo.turn_indices;
+
+ for (typename std::set<signed_size_type>::const_iterator it = ids.begin();
+ it != ids.end(); ++it)
+ {
+ signed_size_type const turn_index = *it;
+ turn_type& turn = m_turns[turn_index];
+
+ for (int i = 0; i < 2; i++)
+ {
+ turn_operation_type& op = turn.operations[i];
+ if (op.visited.none()
+ && op.enriched.rank == rank)
+ {
+ op.visited.set_visited();
+ }
+ }
+ }
+ }
inline void set_visited(turn_type& turn, turn_operation_type& op)
{
- // On "continue", set "visited" for ALL directions in this turn
if (op.operation == detail::overlay::operation_continue)
{
+ // On "continue", all go in same direction so set "visited" for ALL
for (int i = 0; i < 2; i++)
{
turn_operation_type& turn_op = turn.operations[i];
@@ -151,6 +192,10 @@ struct traversal
{
op.visited.set_visited();
}
+ if (turn.cluster_id >= 0)
+ {
+ set_visited_in_cluster(turn.cluster_id, op.enriched.rank);
+ }
}
inline bool is_visited(turn_type const& , turn_operation_type const& op,
@@ -160,8 +205,8 @@ struct traversal
}
inline bool select_source(signed_size_type turn_index,
- segment_identifier const& seg_id1,
- segment_identifier const& seg_id2) const
+ segment_identifier const& candidate_seg_id,
+ segment_identifier const& previous_seg_id) const
{
// For uu/ii, only switch sources if indicated
turn_type const& turn = m_turns[turn_index];
@@ -170,8 +215,16 @@ struct traversal
{
// Buffer does not use source_index (always 0)
return turn.switch_source
- ? seg_id1.multi_index != seg_id2.multi_index
- : seg_id1.multi_index == seg_id2.multi_index;
+ ? candidate_seg_id.multi_index != previous_seg_id.multi_index
+ : candidate_seg_id.multi_index == previous_seg_id.multi_index;
+ }
+
+ if (is_self_turn<OverlayType>(turn))
+ {
+ // Also, if it is a self-turn, stay on same ring (multi/ring)
+ return turn.switch_source
+ ? candidate_seg_id.multi_index != previous_seg_id.multi_index
+ : candidate_seg_id.multi_index == previous_seg_id.multi_index;
}
#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)
@@ -185,16 +238,8 @@ struct traversal
}
#endif
return turn.switch_source
- ? seg_id1.source_index != seg_id2.source_index
- : seg_id1.source_index == seg_id2.source_index;
- }
-
- inline
- signed_size_type get_next_turn_index(turn_operation_type const& op) const
- {
- return op.enriched.next_ip_index == -1
- ? op.enriched.travels_to_ip_index
- : op.enriched.next_ip_index;
+ ? candidate_seg_id.source_index != previous_seg_id.source_index
+ : candidate_seg_id.source_index == previous_seg_id.source_index;
}
inline bool traverse_possible(signed_size_type turn_index) const
@@ -220,39 +265,39 @@ struct traversal
{
// For "cc", take either one, but if there is a starting one,
// take that one. If next is dead end, skip that one.
+ // If both are valid candidates, take the one with minimal remaining
+ // distance (important for #mysql_23023665 in buffer).
- bool result = false;
-
+ // Initialize with 0, automatically assigned on first result
typename turn_operation_type::comparable_distance_type
- max_remaining_distance = 0;
+ min_remaining_distance = 0;
+
+ bool result = false;
for (int i = 0; i < 2; i++)
{
turn_operation_type const& op = turn.operations[i];
- signed_size_type const next_turn_index = get_next_turn_index(op);
+ signed_size_type const next_turn_index = op.enriched.get_next_turn_index();
- if (! result && traverse_possible(next_turn_index))
+ if (! traverse_possible(next_turn_index))
{
- max_remaining_distance = op.remaining_distance;
- selected_op_index = i;
- debug_traverse(turn, op, " Candidate");
- result = true;
+ continue;
}
- if (result)
+ if (! result
+ || next_turn_index == start_turn_index
+ || op.remaining_distance < min_remaining_distance)
{
- if (next_turn_index == start_turn_index)
- {
- selected_op_index = i;
- debug_traverse(turn, op, " Candidate cc override (start)");
- }
- else if (op.remaining_distance > max_remaining_distance)
- {
- max_remaining_distance = op.remaining_distance;
- selected_op_index = i;
- debug_traverse(turn, op, " Candidate cc override (remaining)");
- }
+ debug_traverse(turn, op, "First candidate cc", ! result);
+ debug_traverse(turn, op, "Candidate cc override (start)",
+ result && next_turn_index == start_turn_index);
+ debug_traverse(turn, op, "Candidate cc override (remaining)",
+ result && op.remaining_distance < min_remaining_distance);
+
+ selected_op_index = i;
+ min_remaining_distance = op.remaining_distance;
+ result = true;
}
}
@@ -262,7 +307,7 @@ struct traversal
inline
bool select_noncc_operation(turn_type const& turn,
signed_size_type turn_index,
- segment_identifier const& seg_id,
+ segment_identifier const& previous_seg_id,
int& selected_op_index) const
{
bool result = false;
@@ -273,10 +318,10 @@ struct traversal
if (op.operation == target_operation
&& ! op.visited.finished()
- && (! result || select_source(turn_index, op.seg_id, seg_id)))
+ && (! result || select_source(turn_index, op.seg_id, previous_seg_id)))
{
selected_op_index = i;
- debug_traverse(turn, op, " Candidate");
+ debug_traverse(turn, op, "Candidate");
result = true;
}
}
@@ -305,7 +350,7 @@ struct traversal
}
if (result)
{
- debug_traverse(turn, turn.operations[selected_op_index], " Accepted");
+ debug_traverse(turn, turn.operations[selected_op_index], "Accepted");
}
return result;
@@ -336,108 +381,164 @@ struct traversal
}
inline bool select_from_cluster_union(signed_size_type& turn_index,
- int& op_index, signed_size_type start_turn_index,
- sbs_type const& sbs, bool is_touching) const
+ int& op_index, sbs_type& sbs) const
{
+ std::vector<sort_by_side::rank_with_rings> aggregation;
+ sort_by_side::aggregate_operations(sbs, aggregation, m_turns, operation_union);
+
+
+ sort_by_side::rank_with_rings const& incoming = aggregation.front();
+
+ // Take the first one outgoing for the incoming region
std::size_t selected_rank = 0;
- std::size_t min_rank = 0;
- bool result = false;
- for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
+ for (std::size_t i = 1; i < aggregation.size(); i++)
+ {
+ sort_by_side::rank_with_rings const& rwr = aggregation[i];
+ if (rwr.all_to()
+ && rwr.region_id() == incoming.region_id())
+ {
+ selected_rank = rwr.rank;
+ break;
+ }
+ }
+
+ for (std::size_t i = 1; i < sbs.m_ranked_points.size(); i++)
{
typename sbs_type::rp const& ranked_point = sbs.m_ranked_points[i];
- if (result && ranked_point.rank > selected_rank)
+ if (ranked_point.rank == selected_rank
+ && ranked_point.direction == sort_by_side::dir_to)
{
- return result;
+ turn_index = ranked_point.turn_index;
+ op_index = ranked_point.operation_index;
+
+ turn_type const& turn = m_turns[turn_index];
+ turn_operation_type const& op = turn.operations[op_index];
+
+ if (op.enriched.count_left == 0
+ && op.enriched.count_right > 0
+ && ! op.visited.finalized())
+ {
+ // In some cases interior rings might be generated with polygons
+ // on both sides
+
+ // TODO: this should be finetuned such that checking
+ // finalized is not necessary
+ return true;
+ }
}
+ }
+ return false;
+ }
- turn_type const& ranked_turn = m_turns[ranked_point.turn_index];
- turn_operation_type const& ranked_op = ranked_turn.operations[ranked_point.operation_index];
- if (result && ranked_op.visited.finalized())
+ inline bool all_operations_of_type(sort_by_side::rank_with_rings const& rwr,
+ operation_type op_type,
+ sort_by_side::direction_type dir) const
+ {
+ typedef std::set<sort_by_side::ring_with_direction>::const_iterator sit_type;
+ for (sit_type it = rwr.rings.begin(); it != rwr.rings.end(); ++it)
+ {
+ sort_by_side::ring_with_direction const& rwd = *it;
+ if (rwd.direction != dir)
{
- // One of the arcs in the same direction as the selected result
- // is already traversed.
return false;
}
-
- if (! is_touching && ranked_op.visited.finalized())
+ turn_type const& turn = m_turns[rwd.turn_index];
+ if (! turn.both(op_type))
{
- // Skip this one, go to next
- min_rank = ranked_point.rank;
- continue;
+ return false;
}
- if (ranked_point.direction == sort_by_side::dir_to
- && (ranked_point.rank > min_rank
- || ranked_turn.both(operation_continue)))
+ // Check if this is not yet taken
+ turn_operation_type const& op = turn.operations[rwd.operation_index];
+ if (op.visited.finalized())
{
- if (ranked_op.enriched.count_left == 0
- && ranked_op.enriched.count_right > 0)
- {
- if (result && ranked_point.turn_index != start_turn_index)
- {
- // Don't override - only override if arrive at start
- continue;
- }
-
- turn_index = ranked_point.turn_index;
- op_index = ranked_point.operation_index;
-
- result = true;
- selected_rank = ranked_point.rank;
- }
- else if (! is_touching)
- {
- return result;
- }
+ return false;
}
+
}
- return result;
+ return true;
}
inline bool analyze_cluster_intersection(signed_size_type& turn_index,
- int& op_index,
- sbs_type const& sbs) const
+ int& op_index, sbs_type const& sbs) const
{
std::vector<sort_by_side::rank_with_rings> aggregation;
- sort_by_side::aggregate_operations(sbs, aggregation);
+ sort_by_side::aggregate_operations(sbs, aggregation, m_turns, operation_intersection);
std::size_t selected_rank = 0;
- for (std::size_t i = 0; i < aggregation.size(); i++)
+
+ // Detect specific pattern(s)
+ bool const detected
+ = intersection_pattern_common_interior1(selected_rank, aggregation)
+ || intersection_pattern_common_interior2(selected_rank, aggregation)
+ || intersection_pattern_common_interior3(selected_rank, aggregation)
+ || intersection_pattern_common_interior4(selected_rank, aggregation)
+ ;
+
+ if (! detected)
{
- sort_by_side::rank_with_rings const& rwr = aggregation[i];
+ int incoming_region_id = 0;
+ std::set<int> outgoing_region_ids;
- if (i > 1
- && i - 1 == selected_rank
- && rwr.rings.size() == 1)
+ for (std::size_t i = 0; i < aggregation.size(); i++)
{
- sort_by_side::ring_with_direction const& rwd = *rwr.rings.begin();
+ sort_by_side::rank_with_rings const& rwr = aggregation[i];
- if (rwd.only_turn_on_ring)
+ if (rwr.all_to()
+ && rwr.traversable(m_turns)
+ && selected_rank == 0)
{
- // Find if this arriving ring was leaving previously
- sort_by_side::ring_with_direction leaving = rwd;
- leaving.direction = sort_by_side::dir_to;
-
- sort_by_side::rank_with_rings const& previous = aggregation[i - 1];
+ // Take the first (= right) where segments leave,
+ // having the polygon on the right side
+ selected_rank = rwr.rank;
+ }
- if (previous.rings.size() == 1
- && previous.rings.count(leaving) == 1)
- {
- // It arrives back - if this is one of the selected, unselect it
- selected_rank = 0;
- }
+ if (rwr.all_from()
+ && selected_rank > 0
+ && outgoing_region_ids.empty())
+ {
+ // Incoming
+ break;
}
- }
- if (rwr.all_to())
- {
- if (selected_rank == 0)
+ if (incoming_region_id == 0)
{
- // Take the first (= right) where segments leave,
- // having the polygon on the right side
- selected_rank = rwr.rank;
+ sort_by_side::ring_with_direction const& rwd = *rwr.rings.begin();
+ turn_type const& turn = m_turns[rwd.turn_index];
+ incoming_region_id = turn.operations[rwd.operation_index].enriched.region_id;
+ }
+ else
+ {
+ if (rwr.rings.size() == 1)
+ {
+ sort_by_side::ring_with_direction const& rwd = *rwr.rings.begin();
+ turn_type const& turn = m_turns[rwd.turn_index];
+ if (rwd.direction == sort_by_side::dir_to
+ && turn.both(operation_intersection))
+ {
+
+ turn_operation_type const& op = turn.operations[rwd.operation_index];
+ if (op.enriched.region_id != incoming_region_id
+ && op.enriched.isolated)
+ {
+ outgoing_region_ids.insert(op.enriched.region_id);
+ }
+ }
+ else if (! outgoing_region_ids.empty())
+ {
+ for (int i = 0; i < 2; i++)
+ {
+ int const region_id = turn.operations[i].enriched.region_id;
+ if (outgoing_region_ids.count(region_id) == 1)
+ {
+ selected_rank = 0;
+ outgoing_region_ids.erase(region_id);
+ }
+ }
+ }
+ }
}
}
}
@@ -458,7 +559,7 @@ struct traversal
{
// This direction is already traveled before, the same
// cannot be traveled again
- return false;
+ continue;
}
// Take the last turn from this rank
@@ -479,10 +580,9 @@ struct traversal
}
inline bool select_turn_from_cluster(signed_size_type& turn_index,
- int& op_index, bool& is_touching,
+ int& op_index,
signed_size_type start_turn_index,
- segment_identifier const& previous_seg_id,
- bool is_start) const
+ segment_identifier const& previous_seg_id) const
{
bool const is_union = target_operation == operation_union;
@@ -495,15 +595,14 @@ struct traversal
cluster_info const& cinfo = mit->second;
std::set<signed_size_type> const& ids = cinfo.turn_indices;
- sbs_type sbs;
-
- bool has_origin = false;
+ sbs_type sbs(m_strategy);
for (typename std::set<signed_size_type>::const_iterator sit = ids.begin();
sit != ids.end(); ++sit)
{
signed_size_type cluster_turn_index = *sit;
turn_type const& cluster_turn = m_turns[cluster_turn_index];
+ bool const departure_turn = cluster_turn_index == turn_index;
if (cluster_turn.discarded)
{
// Defensive check, discarded turns should not be in cluster
@@ -512,79 +611,27 @@ struct traversal
for (int i = 0; i < 2; i++)
{
- turn_operation_type const& op = cluster_turn.operations[i];
- bool is_origin = false;
- if (cluster_turn_index == turn_index)
- {
- // Check if this is the origin
- if (OverlayType == overlay_buffer)
- {
- is_origin = op.seg_id.multi_index == previous_seg_id.multi_index;
- }
- else
- {
- is_origin = op.seg_id.source_index
- == previous_seg_id.source_index;
- }
- if (is_origin)
- {
- has_origin = true;
- }
- }
-
- sbs.add(op, cluster_turn_index, i, m_geometry1, m_geometry2,
- is_origin);
+ sbs.add(cluster_turn.operations[i],
+ cluster_turn_index, i, previous_seg_id,
+ m_geometry1, m_geometry2,
+ departure_turn);
}
}
- if (! has_origin)
+ if (! sbs.has_origin())
{
return false;
}
-
sbs.apply(turn.point);
bool result = false;
if (is_union)
{
- #if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)
- is_touching = cinfo.open_count > 1;
- if (is_touching)
- {
- if (cinfo.switch_source)
- {
- is_touching = false;
- std::cout << "CLUSTER: SWITCH SOURCES at " << turn_index << std::endl;
- }
- else
- {
- std::cout << "CLUSTER: CONTINUE at " << turn_index << std::endl;
- }
- }
- #else
- is_touching = cinfo.open_count > 1 && ! cinfo.switch_source;
- #endif
-
- if (is_touching)
- {
- sbs.reverse();
- }
-
- result = select_from_cluster_union(turn_index, op_index, start_turn_index, sbs,
- is_touching);
+ result = select_from_cluster_union(turn_index, op_index, sbs);
}
else
{
- if (is_start
- && turn.both(operation_intersection)
- && turn.operations[op_index].enriched.only_turn_on_ring)
- {
- // For an ii (usually interior ring), only turn on ring,
- // reverse to take first exit
- sbs.reverse();
- }
-
result = analyze_cluster_intersection(turn_index, op_index, sbs);
}
return result;
@@ -594,26 +641,27 @@ struct traversal
turn_type const& current_turn,
segment_identifier const& previous_seg_id)
{
- sbs_type sbs;
+ sbs_type sbs(m_strategy);
// Add this turn to the sort-by-side sorter
- bool has_origin = false;
for (int i = 0; i < 2; i++)
{
- turn_operation_type const& op = current_turn.operations[i];
- bool const is_origin = op.seg_id.source_index
- == previous_seg_id.source_index;
- has_origin = has_origin || is_origin;
- sbs.add(op, turn_index, i, m_geometry1, m_geometry2, is_origin);
+ sbs.add(current_turn.operations[i],
+ turn_index, i, previous_seg_id,
+ m_geometry1, m_geometry2,
+ true);
}
- if (! has_origin)
+ if (! sbs.has_origin())
{
return false;
}
sbs.apply(current_turn.point);
- return analyze_cluster_intersection(turn_index, op_index, sbs);
+
+ bool result = analyze_cluster_intersection(turn_index, op_index, sbs);
+
+ return result;
}
inline void change_index_for_self_turn(signed_size_type& to_vertex_index,
@@ -712,7 +760,6 @@ struct traversal
bool select_turn(signed_size_type start_turn_index, int start_op_index,
signed_size_type& turn_index,
int& op_index,
- bool& is_touching,
int previous_op_index,
signed_size_type previous_turn_index,
segment_identifier const& previous_seg_id,
@@ -737,8 +784,8 @@ struct traversal
if (current_turn.cluster_id < 0
&& current_turn.both(operation_intersection))
{
- if (analyze_ii_intersection(turn_index, op_index, current_turn,
- previous_seg_id))
+ if (analyze_ii_intersection(turn_index, op_index,
+ current_turn, previous_seg_id))
{
return true;
}
@@ -747,8 +794,8 @@ struct traversal
if (current_turn.cluster_id >= 0)
{
- if (! select_turn_from_cluster(turn_index, op_index, is_touching,
- start_turn_index, previous_seg_id, is_start))
+ if (! select_turn_from_cluster(turn_index, op_index,
+ start_turn_index, previous_seg_id))
{
return false;
}
@@ -786,6 +833,7 @@ private :
Turns& m_turns;
Clusters const& m_clusters;
RobustPolicy const& m_robust_policy;
+ SideStrategy m_strategy;
Visitor& m_visitor;
};
diff --git a/boost/geometry/algorithms/detail/overlay/traversal_intersection_patterns.hpp b/boost/geometry/algorithms/detail/overlay/traversal_intersection_patterns.hpp
new file mode 100644
index 0000000000..12279d762f
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/traversal_intersection_patterns.hpp
@@ -0,0 +1,306 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2017 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the 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_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_INTERSECTION_PATTERNS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_INTERSECTION_PATTERNS_HPP
+
+#include <cstddef>
+#include <vector>
+
+#include <boost/geometry/algorithms/detail/overlay/aggregate_operations.hpp>
+#include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+inline bool check_pairs(std::vector<sort_by_side::rank_with_rings> const& aggregation,
+ signed_size_type incoming_region_id,
+ std::size_t first, std::size_t last)
+{
+ // Check if pairs 1,2 (and possibly 3,4 and 5,6 etc) satisfy
+
+ for (std::size_t i = first; i <= last; i += 2)
+ {
+ sort_by_side::rank_with_rings const& curr = aggregation[i];
+ sort_by_side::rank_with_rings const& next = aggregation[i + 1];
+ int const curr_id = curr.region_id();
+ int const next_id = next.region_id();
+
+ bool const possible =
+ curr.rings.size() == 2
+ && curr.is_isolated()
+ && curr.has_unique_region_id()
+ && next.rings.size() == 2
+ && next.is_isolated()
+ && next.has_unique_region_id()
+ && curr_id == next_id
+ && curr_id != incoming_region_id;
+
+ if (! possible)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+inline bool intersection_pattern_common_interior1(std::size_t& selected_rank,
+ std::vector<sort_by_side::rank_with_rings> const& aggregation)
+{
+ // Pattern: coming from exterior ring, encountering an isolated
+ // parallel interior ring, which should be skipped, and the first
+ // left (normally intersection takes first right) should be taken.
+ // Solves cases #case_133_multi
+ // and #case_recursive_boxes_49
+
+ std::size_t const n = aggregation.size();
+ if (n < 4)
+ {
+ return false;
+ }
+
+ sort_by_side::rank_with_rings const& incoming = aggregation.front();
+ sort_by_side::rank_with_rings const& outgoing = aggregation.back();
+
+ bool const incoming_ok =
+ incoming.all_from()
+ && incoming.rings.size() == 1
+ && incoming.has_only(operation_intersection);
+
+ if (! incoming_ok)
+ {
+ return false;
+ }
+
+ bool const outgoing_ok =
+ outgoing.all_to()
+ && outgoing.rings.size() == 1
+ && outgoing.has_only(operation_intersection)
+ && outgoing.region_id() == incoming.region_id();
+
+ if (! outgoing_ok)
+ {
+ return false;
+ }
+
+ if (check_pairs(aggregation, incoming.region_id(), 1, n - 2))
+ {
+ selected_rank = n - 1;
+ return true;
+ }
+ return false;
+}
+
+inline bool intersection_pattern_common_interior2(std::size_t& selected_rank,
+ std::vector<sort_by_side::rank_with_rings> const& aggregation)
+{
+ // Pattern: coming from two exterior rings, encountering two isolated
+ // equal interior rings
+
+ // See (for example, for ii) #case_recursive_boxes_53:
+
+ // INCOMING:
+ // Rank 0 {11[0] (s:0, m:0) i F rgn: 1 ISO} {13[1] (s:1, m:0) i F rgn: 1 ISO}
+
+ // PAIR:
+ // Rank 1 {13[0] (s:0, r:1, m:0) i T rgn: 3 ISO ->16} {11[1] (s:1, r:5, m:0) i T rgn: 3 ISO ->16}
+ // Rank 2 {13[0] (s:0, r:1, m:0) i F rgn: 3 ISO} {11[1] (s:1, r:5, m:0) i F rgn: 3 ISO}
+
+ // LEAVING (in the same direction, take last one)
+ // Rank 3 {11[0] (s:0, m:0) i T rgn: 1 ISO ->10} {13[1] (s:1, m:0) i T rgn: 1 ISO ->10}
+
+
+ std::size_t const n = aggregation.size();
+ if (n < 4)
+ {
+ return false;
+ }
+
+ sort_by_side::rank_with_rings const& incoming = aggregation.front();
+ sort_by_side::rank_with_rings const& outgoing = aggregation.back();
+
+ bool const incoming_ok =
+ incoming.all_from()
+ && incoming.rings.size() == 2
+ && incoming.has_unique_region_id();
+
+ if (! incoming_ok)
+ {
+ return false;
+ }
+
+ bool const outgoing_ok =
+ outgoing.all_to()
+ && outgoing.rings.size() == 2
+ && outgoing.has_unique_region_id()
+ && outgoing.region_id() == incoming.region_id();
+
+ if (! outgoing_ok)
+ {
+ return false;
+ }
+
+ bool const operation_ok =
+ (incoming.has_only(operation_continue) && outgoing.has_only(operation_continue))
+ || (incoming.has_only(operation_intersection) && outgoing.has_only(operation_intersection));
+
+ if (! operation_ok)
+ {
+ return false;
+ }
+
+ // Check if pairs 1,2 (and possibly 3,4 and 5,6 etc) satisfy
+ if (check_pairs(aggregation, incoming.region_id(), 1, n - 2))
+ {
+ selected_rank = n - 1;
+ return true;
+ }
+ return false;
+}
+
+inline bool intersection_pattern_common_interior3(std::size_t& selected_rank,
+ std::vector<sort_by_side::rank_with_rings> const& aggregation)
+{
+ // Pattern: approaches colocated turn (exterior+interior) from two
+ // different directions, and both leaves in the same direction
+
+ // See #case_136_multi:
+ // INCOMING:
+ //Rank 0 {10[0] (s:0, m:0) c F rgn: 1 ISO}
+
+ // PAIR:
+ //Rank 1 {14[0] (s:0, r:0, m:0) i T rgn: 2 ISO ->16} {11[1] (s:1, r:1, m:0) i T rgn: 2 ISO ->16}
+ //Rank 2 {14[0] (s:0, r:0, m:0) i F rgn: 2 ISO} {11[1] (s:1, r:1, m:0) i F rgn: 2 ISO}
+
+ // LEAVING (select this one):
+ //Rank 3 {10[0] (s:0, m:0) c T rgn: 1 ISO ->12} {10[1] (s:1, m:0) c T rgn: 1 ISO ->12}
+
+ // ADDITIONALLY: (other polygon coming in)
+ //Rank 4 {10[1] (s:1, m:0) c F rgn: 1 ISO}
+
+ std::size_t const n = aggregation.size();
+ if (n < 4)
+ {
+ return false;
+ }
+
+ sort_by_side::rank_with_rings const& incoming = aggregation.front();
+ sort_by_side::rank_with_rings const& outgoing = aggregation[n - 2];
+ sort_by_side::rank_with_rings const& last = aggregation.back();
+
+ bool const incoming_ok =
+ incoming.all_from()
+ && incoming.rings.size() == 1
+ && incoming.has_only(operation_continue);
+
+ if (! incoming_ok)
+ {
+ return false;
+ }
+
+ bool const outgoing_ok =
+ outgoing.all_to()
+ && outgoing.rings.size() == 2
+ && outgoing.has_only(operation_continue)
+ && outgoing.has_unique_region_id()
+ && outgoing.region_id() == incoming.region_id()
+ && last.all_from()
+ && last.rings.size() == 1
+ && last.region_id() == incoming.region_id()
+ && last.all_from();
+
+ if (! outgoing_ok)
+ {
+ return false;
+ }
+
+ // Check if pairs 1,2 (and possibly 3,4 and 5,6 etc) satisfy
+ if (check_pairs(aggregation, incoming.region_id(), 1, n - 3))
+ {
+ selected_rank = n - 2;
+ return true;
+ }
+ return false;
+}
+
+
+inline bool intersection_pattern_common_interior4(std::size_t& selected_rank,
+ std::vector<sort_by_side::rank_with_rings> const& aggregation)
+{
+ // Pattern: approaches colocated turn (exterior+interior) from same
+ // direction, but leaves in two different directions
+
+ // See #case_137_multi:
+
+ // INCOMING:
+ //Rank 0 {11[0] (s:0, m:0) i F rgn: 1 ISO} {10[1] (s:1, m:0) i F rgn: 1 ISO}
+
+ // PAIR:
+ //Rank 1 {13[0] (s:0, r:0, m:0) i T rgn: 2 ISO ->15} {11[1] (s:1, r:1, m:0) i T rgn: 2 ISO ->15}
+ //Rank 2 {13[0] (s:0, r:0, m:0) i F rgn: 2 ISO} {11[1] (s:1, r:1, m:0) i F rgn: 2 ISO}
+
+ // LEAVING (in two different directions, take last one)
+ //Rank 3 {10[1] (s:1, m:0) i T rgn: 1 ISO ->0}
+ //Rank 4 {11[0] (s:0, m:0) i T rgn: 1 ISO ->12}
+
+ std::size_t const n = aggregation.size();
+ if (n < 4)
+ {
+ return false;
+ }
+
+ sort_by_side::rank_with_rings const& incoming = aggregation.front();
+ sort_by_side::rank_with_rings const& extra = aggregation[n - 2];
+ sort_by_side::rank_with_rings const& outgoing = aggregation.back();
+
+ bool const incoming_ok =
+ incoming.all_from()
+ && incoming.rings.size() == 2
+ && incoming.has_unique_region_id()
+ && incoming.has_only(operation_intersection);
+
+ if (! incoming_ok)
+ {
+ return false;
+ }
+
+ bool const outgoing_ok =
+ outgoing.all_to()
+ && outgoing.rings.size() == 1
+ && outgoing.has_only(operation_intersection)
+ && outgoing.region_id() == incoming.region_id()
+ && extra.all_to()
+ && extra.rings.size() == 1
+ && extra.has_only(operation_intersection)
+ && extra.region_id() == incoming.region_id();
+
+ if (! outgoing_ok)
+ {
+ return false;
+ }
+
+ // Check if pairs 1,2 (and possibly 3,4 and 5,6 etc) satisfy
+ if (check_pairs(aggregation, incoming.region_id(), 1, n - 3))
+ {
+ selected_rank = n - 1;
+ return true;
+ }
+ return false;
+}
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_INTERSECTION_PATTERNS_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp b/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp
index 9ab82a77c1..af643a822b 100644
--- a/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp
@@ -49,9 +49,13 @@ template
>
struct traversal_ring_creator
{
- typedef traversal<Reverse1, Reverse2, OverlayType,
- Geometry1, Geometry2, Turns, Clusters, RobustPolicy, Visitor>
- traversal_type;
+ typedef traversal
+ <
+ Reverse1, Reverse2, OverlayType,
+ Geometry1, Geometry2, Turns, Clusters,
+ RobustPolicy, typename IntersectionStrategy::side_strategy_type,
+ Visitor
+ > traversal_type;
typedef typename boost::range_value<Turns>::type turn_type;
typedef typename turn_type::turn_operation_type turn_operation_type;
@@ -63,7 +67,9 @@ struct traversal_ring_creator
Turns& turns, Clusters const& clusters,
IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy, Visitor& visitor)
- : m_trav(geometry1, geometry2, turns, clusters, robust_policy,visitor)
+ : m_trav(geometry1, geometry2, turns, clusters,
+ robust_policy, intersection_strategy.get_side_strategy(),
+ visitor)
, m_geometry1(geometry1)
, m_geometry2(geometry2)
, m_turns(turns)
@@ -103,12 +109,14 @@ struct traversal_ring_creator
{
geometry::copy_segments<Reverse1>(m_geometry1,
previous_op.seg_id, to_vertex_index,
+ m_intersection_strategy.get_side_strategy(),
m_robust_policy, current_ring);
}
else
{
geometry::copy_segments<Reverse2>(m_geometry2,
previous_op.seg_id, to_vertex_index,
+ m_intersection_strategy.get_side_strategy(),
m_robust_policy, current_ring);
}
}
@@ -127,10 +135,8 @@ struct traversal_ring_creator
m_visitor.visit_traverse(m_turns, previous_turn, previous_op, "Start");
}
- bool is_touching = false;
if (! m_trav.select_turn(start_turn_index, start_op_index,
turn_index, op_index,
- is_touching,
previous_op_index, previous_turn_index, previous_seg_id,
is_start))
{
@@ -154,6 +160,7 @@ struct traversal_ring_creator
turn_type& current_turn = m_turns[turn_index];
turn_operation_type& op = current_turn.operations[op_index];
detail::overlay::append_no_dups_or_spikes(current_ring, current_turn.point,
+ m_intersection_strategy.get_side_strategy(),
m_robust_policy);
// Register the visit
@@ -171,6 +178,7 @@ struct traversal_ring_creator
turn_operation_type& start_op = m_turns[start_turn_index].operations[start_op_index];
detail::overlay::append_no_dups_or_spikes(ring, start_turn.point,
+ m_intersection_strategy.get_side_strategy(),
m_robust_policy);
signed_size_type current_turn_index = start_turn_index;
@@ -273,7 +281,9 @@ struct traversal_ring_creator
if (geometry::num_points(ring) >= min_num_points)
{
- clean_closing_dups_and_spikes(ring, m_robust_policy);
+ clean_closing_dups_and_spikes(ring,
+ m_intersection_strategy.get_side_strategy(),
+ m_robust_policy);
rings.push_back(ring);
m_trav.finalize_visit_info();
@@ -307,11 +317,27 @@ struct traversal_ring_creator
continue;
}
- for (int op_index = 0; op_index < 2; op_index++)
+ if (turn.both(operation_continue))
{
+ // Traverse only one turn, the one with the SMALLEST remaining distance
+ // to avoid skipping a turn in between, which can happen in rare cases
+ // (e.g. #130)
+ turn_operation_type const& op0 = turn.operations[0];
+ turn_operation_type const& op1 = turn.operations[1];
+ int const op_index
+ = op0.remaining_distance <= op1.remaining_distance ? 0 : 1;
+
traverse_with_operation(turn, turn_index, op_index,
rings, finalized_ring_size, state);
}
+ else
+ {
+ for (int op_index = 0; op_index < 2; op_index++)
+ {
+ traverse_with_operation(turn, turn_index, op_index,
+ rings, finalized_ring_size, state);
+ }
+ }
}
}
diff --git a/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp b/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp
index 183131c74b..0b4f393ef4 100644
--- a/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp
@@ -16,6 +16,7 @@
#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>
#include <boost/geometry/algorithms/detail/overlay/cluster_info.hpp>
+#include <boost/geometry/algorithms/detail/overlay/is_self_turn.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/assert.hpp>
@@ -47,10 +48,54 @@ template
>
struct traversal_switch_detector
{
+ enum isolation_type { isolation_unknown = -1, isolation_no = 0, isolation_yes = 1 };
+
typedef typename boost::range_value<Turns>::type turn_type;
typedef typename turn_type::turn_operation_type turn_operation_type;
- // For convenience
+ // Per ring, first turns are collected (in turn_indices), and later
+ // a region_id is assigned
+ struct merged_ring_properties
+ {
+ signed_size_type region_id;
+ std::set<signed_size_type> turn_indices;
+
+ merged_ring_properties()
+ : region_id(-1)
+ {}
+ };
+
+ struct connection_properties
+ {
+ std::size_t count;
+ std::set<signed_size_type> cluster_indices;
+ connection_properties()
+ : count(0)
+ {}
+ };
+
+ typedef std::map<signed_size_type, connection_properties> connection_map;
+
+ // Per region, a set of properties is maintained, including its connections
+ // to other regions
+ struct region_properties
+ {
+ signed_size_type region_id;
+ isolation_type isolated;
+
+ // Maps from connected region_id to their properties
+ connection_map connected_region_counts;
+
+ region_properties()
+ : region_id(-1)
+ , isolated(isolation_unknown)
+ {}
+ };
+
+ // Keeps turn indices per ring
+ typedef std::map<ring_identifier, merged_ring_properties > merge_map;
+ typedef std::map<signed_size_type, region_properties> region_connection_map;
+
typedef std::set<signed_size_type>::const_iterator set_iterator;
inline traversal_switch_detector(Geometry1 const& geometry1, Geometry2 const& geometry2,
@@ -62,135 +107,309 @@ struct traversal_switch_detector
, m_clusters(clusters)
, m_robust_policy(robust_policy)
, m_visitor(visitor)
- , m_region_id(0)
{
+ }
+
+ isolation_type get_isolation(region_properties const& properties,
+ signed_size_type parent_region_id,
+ const std::set<signed_size_type>& visited)
+ {
+ if (properties.isolated != isolation_unknown)
+ {
+ return properties.isolated;
+ }
+
+ bool all_colocated = true;
+ int unique_cluster_id = -1;
+ for (typename connection_map::const_iterator it = properties.connected_region_counts.begin();
+ all_colocated && it != properties.connected_region_counts.end(); ++it)
+ {
+ connection_properties const& cprop = it->second;
+ if (cprop.cluster_indices.size() != 1)
+ {
+ // Either no cluster (non colocated point), or more clusters
+ all_colocated = false;
+ }
+ int const cluster_id = *cprop.cluster_indices.begin();
+ if (cluster_id == -1)
+ {
+ all_colocated = false;
+ }
+ else if (unique_cluster_id == -1)
+ {
+ unique_cluster_id = cluster_id;
+ }
+ else if (unique_cluster_id != cluster_id)
+ {
+ all_colocated = false;
+ }
+ }
+ if (all_colocated)
+ {
+ return isolation_yes;
+ }
+
+
+ // It is isolated if there is only one connection, or if there are more connections but all
+ // of them are isolated themselves, or if there are more connections
+ // but they are all colocated
+ std::size_t non_isolation_count = 0;
+ bool child_not_isolated = false;
+ for (typename connection_map::const_iterator it = properties.connected_region_counts.begin();
+ it != properties.connected_region_counts.end(); ++it)
+ {
+ signed_size_type const region_id = it->first;
+ connection_properties const& cprop = it->second;
+
+ if (region_id == parent_region_id)
+ {
+ // Normal situation, skip its direct parent
+ continue;
+ }
+ if (visited.count(region_id) > 0)
+ {
+ // Find one of its ancestors again, this is a ring. Not isolated.
+ return isolation_no;
+ }
+ if (cprop.count > 1)
+ {
+ return isolation_no;
+ }
+
+ typename region_connection_map::iterator mit = m_connected_regions.find(region_id);
+ if (mit == m_connected_regions.end())
+ {
+ // Should not occur
+ continue;
+ }
+
+ std::set<signed_size_type> vis = visited;
+ vis.insert(parent_region_id);
+ region_properties& prop = mit->second;
+ if (prop.isolated == isolation_unknown)
+ {
+ isolation_type const iso = get_isolation(prop, properties.region_id, vis);
+ prop.isolated = iso;
+ if (iso == isolation_no)
+ {
+ child_not_isolated = true;
+ }
+ }
+ if (prop.isolated == isolation_no)
+ {
+ non_isolation_count++;
+ }
+ }
+
+ return child_not_isolated || non_isolation_count > 1 ? isolation_no : isolation_yes;
}
- static inline bool connects_same_zone(turn_type const& turn)
+ void get_isolated_regions()
{
+ for (typename region_connection_map::iterator it = m_connected_regions.begin();
+ it != m_connected_regions.end(); ++it)
+ {
+ region_properties& properties = it->second;
+ if (properties.isolated == isolation_unknown)
+ {
+ std::set<signed_size_type> visited;
+ properties.isolated = get_isolation(properties, properties.region_id, visited);
+ }
+ }
+ }
+
+ void assign_isolation()
+ {
+ for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index)
+ {
+ turn_type& turn = m_turns[turn_index];
+
+ for (int op_index = 0; op_index < 2; op_index++)
+ {
+ turn_operation_type& op = turn.operations[op_index];
+ typename region_connection_map::const_iterator mit = m_connected_regions.find(op.enriched.region_id);
+ if (mit != m_connected_regions.end())
+ {
+ region_properties const& prop = mit->second;
+ op.enriched.isolated = prop.isolated == isolation_yes;
+ }
+ }
+ }
+ }
+
+ void assign_regions()
+ {
+ for (typename merge_map::const_iterator it
+ = m_turns_per_ring.begin(); it != m_turns_per_ring.end(); ++it)
+ {
+ ring_identifier const& ring_id = it->first;
+ merged_ring_properties const& properties = it->second;
+
+ for (set_iterator sit = properties.turn_indices.begin();
+ sit != properties.turn_indices.end(); ++sit)
+ {
+ turn_type& turn = m_turns[*sit];
+
+ for (int i = 0; i < 2; i++)
+ {
+ turn_operation_type& op = turn.operations[i];
+ if (ring_id_by_seg_id(op.seg_id) == ring_id)
+ {
+ op.enriched.region_id = properties.region_id;
+ }
+ }
+ signed_size_type const& id0 = turn.operations[0].enriched.region_id;
+ signed_size_type const& id1 = turn.operations[1].enriched.region_id;
+ if (id0 != id1 && id0 != -1 && id1 != -1)
+ {
+ // Force insertion
+ m_connected_regions[id0].region_id = id0;
+ m_connected_regions[id1].region_id = id1;
+
+ connection_properties& prop0 = m_connected_regions[id0].connected_region_counts[id1];
+ connection_properties& prop1 = m_connected_regions[id1].connected_region_counts[id0];
+
+ if (turn.cluster_id < 0)
+ {
+ // Turn is not colocated, add reference to connection
+ prop0.count++;
+ prop1.count++;
+ }
+ else
+ {
+ // Turn is colocated, only add region reference if it was not yet registered
+ if (prop0.cluster_indices.count(turn.cluster_id) == 0)
+ {
+ prop0.count++;
+ }
+ if (prop1.cluster_indices.count(turn.cluster_id) == 0)
+ {
+ prop1.count++;
+ }
+ }
+ // Insert cluster-id (also -1 is inserted - reinsertion of
+ // same cluster id is OK)
+ prop0.cluster_indices.insert(turn.cluster_id);
+ prop1.cluster_indices.insert(turn.cluster_id);
+ }
+ }
+ }
+ }
+
+ inline bool connects_same_region(turn_type const& turn) const
+ {
+ if (turn.discarded)
+ {
+ // Discarded turns don't connect same region (otherwise discarded colocated uu turn
+ // could make a connection)
+ return false;
+ }
+
if (turn.cluster_id == -1)
{
- // If it is a uu/ii-turn (non clustered), it is never same zone
+ // If it is a uu/ii-turn (non clustered), it is never same region
return ! (turn.both(operation_union) || turn.both(operation_intersection));
}
- // It is a cluster, check zones of both operations
- return turn.operations[0].enriched.zone
- == turn.operations[1].enriched.zone;
+ if (operation_from_overlay<OverlayType>::value == operation_union)
+ {
+ // It is a cluster, check zones
+ // (assigned by sort_by_side/handle colocations) of both operations
+ return turn.operations[0].enriched.zone
+ == turn.operations[1].enriched.zone;
+ }
+
+ // If a cluster contains an ii/cc it is not same region (for intersection)
+ typename Clusters::const_iterator it = m_clusters.find(turn.cluster_id);
+ if (it == m_clusters.end())
+ {
+ // Should not occur
+ return true;
+ }
+
+ cluster_info const& cinfo = it->second;
+ for (set_iterator sit = cinfo.turn_indices.begin();
+ sit != cinfo.turn_indices.end(); ++sit)
+ {
+ turn_type const& cluster_turn = m_turns[*sit];
+ if (cluster_turn.both(operation_union)
+ || cluster_turn.both(operation_intersection))
+ {
+ return false;
+ }
+ }
+
+ // It is the same region
+ return false;
}
+
inline int get_region_id(turn_operation_type const& op) const
{
- std::map<ring_identifier, int>::const_iterator it
- = m_regions.find(ring_id_by_seg_id(op.seg_id));
- return it == m_regions.end() ? -1 : it->second;
+ return op.enriched.region_id;
}
- void create_region(ring_identifier const& ring_id, std::set<signed_size_type> const& ring_turn_indices, int region_id = -1)
+
+ void create_region(signed_size_type& new_region_id, ring_identifier const& ring_id,
+ merged_ring_properties& properties, int region_id = -1)
{
- std::map<ring_identifier, int>::const_iterator it = m_regions.find(ring_id);
- if (it != m_regions.end())
+ if (properties.region_id > 0)
{
- // The ring is already gathered in a region, quit
+ // Already handled
return;
}
+
+ // Assign new id if this is a new region
if (region_id == -1)
{
- region_id = m_region_id++;
+ region_id = new_region_id++;
}
// Assign this ring to specified region
- m_regions[ring_id] = region_id;
+ properties.region_id = region_id;
+
#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)
std::cout << " ADD " << ring_id << " TO REGION " << region_id << std::endl;
#endif
// Find connecting rings, recursively
- for (set_iterator sit = ring_turn_indices.begin();
- sit != ring_turn_indices.end(); ++sit)
+ for (set_iterator sit = properties.turn_indices.begin();
+ sit != properties.turn_indices.end(); ++sit)
{
signed_size_type const turn_index = *sit;
turn_type const& turn = m_turns[turn_index];
- if (! connects_same_zone(turn))
+ if (! connects_same_region(turn))
{
// This is a non clustered uu/ii-turn, or a cluster connecting different 'zones'
continue;
}
- // This turn connects two rings (interior connected), create the
- // same region
+ // Union: This turn connects two rings (interior connected), create the region
+ // Intersection: This turn connects two rings, set same regions for these two rings
for (int op_index = 0; op_index < 2; op_index++)
{
turn_operation_type const& op = turn.operations[op_index];
ring_identifier connected_ring_id = ring_id_by_seg_id(op.seg_id);
if (connected_ring_id != ring_id)
{
- propagate_region(connected_ring_id, region_id);
+ propagate_region(new_region_id, connected_ring_id, region_id);
}
}
}
}
- void check_turns_per_ring(ring_identifier const& ring_id,
- std::set<signed_size_type> const& ring_turn_indices)
+ void propagate_region(signed_size_type& new_region_id,
+ ring_identifier const& ring_id, int region_id)
{
- bool only_turn_on_ring = true;
- if (ring_turn_indices.size() > 1)
- {
- // More turns on this ring. Only leave only_turn_on_ring true
- // if they are all of the same cluster
- int cluster_id = -1;
- for (set_iterator sit = ring_turn_indices.begin();
- sit != ring_turn_indices.end(); ++sit)
- {
- turn_type const& turn = m_turns[*sit];
- if (turn.cluster_id == -1)
- {
- // Unclustered turn - and there are 2 or more turns
- // so the ring has different turns
- only_turn_on_ring = false;
- break;
- }
-
- // Clustered turn, check if it is the first or same as previous
- if (cluster_id == -1)
- {
- cluster_id = turn.cluster_id;
- }
- else if (turn.cluster_id != cluster_id)
- {
- only_turn_on_ring = false;
- break;
- }
- }
- }
-
- // Assign result to matching operation (a turn is always on two rings)
- for (set_iterator sit = ring_turn_indices.begin();
- sit != ring_turn_indices.end(); ++sit)
- {
- turn_type& turn = m_turns[*sit];
- for (int i = 0; i < 2; i++)
- {
- turn_operation_type& op = turn.operations[i];
- if (ring_id_by_seg_id(op.seg_id) == ring_id)
- {
- op.enriched.only_turn_on_ring = only_turn_on_ring;
- }
- }
- }
- }
-
- void propagate_region(ring_identifier const& ring_id, int region_id)
- {
- std::map<ring_identifier, std::set<signed_size_type> >::const_iterator it = m_turns_per_ring.find(ring_id);
+ typename merge_map::iterator it = m_turns_per_ring.find(ring_id);
if (it != m_turns_per_ring.end())
{
- create_region(ring_id, it->second, region_id);
+ create_region(new_region_id, ring_id, it->second, region_id);
}
}
+
void iterate()
{
#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)
@@ -199,26 +418,38 @@ struct traversal_switch_detector
// Collect turns per ring
m_turns_per_ring.clear();
- m_regions.clear();
- m_region_id = 1;
+ m_connected_regions.clear();
for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index)
{
turn_type const& turn = m_turns[turn_index];
+ if (turn.discarded
+ && operation_from_overlay<OverlayType>::value == operation_intersection)
+ {
+ // Discarded turn (union currently still needs it to determine regions)
+ continue;
+ }
+
for (int op_index = 0; op_index < 2; op_index++)
{
turn_operation_type const& op = turn.operations[op_index];
- m_turns_per_ring[ring_id_by_seg_id(op.seg_id)].insert(turn_index);
+ m_turns_per_ring[ring_id_by_seg_id(op.seg_id)].turn_indices.insert(turn_index);
}
}
// All rings having turns are in the map. Now iterate them
- for (std::map<ring_identifier, std::set<signed_size_type> >::const_iterator it
- = m_turns_per_ring.begin(); it != m_turns_per_ring.end(); ++it)
{
- create_region(it->first, it->second);
- check_turns_per_ring(it->first, it->second);
+ signed_size_type new_region_id = 1;
+ for (typename merge_map::iterator it
+ = m_turns_per_ring.begin(); it != m_turns_per_ring.end(); ++it)
+ {
+ create_region(new_region_id, it->first, it->second);
+ }
+
+ assign_regions();
+ get_isolated_regions();
+ assign_isolation();
}
// Now that all regions are filled, assign switch_source property
@@ -245,6 +476,10 @@ struct traversal_switch_detector
{
signed_size_type turn_index = *sit;
turn_type const& turn = m_turns[turn_index];
+ if (turn.colocated_ii && ! turn.colocated_uu)
+ {
+ continue;
+ }
for (int oi = 0; oi < 2; oi++)
{
int const region = get_region_id(turn.operations[oi]);
@@ -252,7 +487,7 @@ struct traversal_switch_detector
}
}
// Switch source if this cluster connects the same region
- cinfo.switch_source = regions.size() == 1;
+ cinfo.switch_source = regions.size() <= 1;
}
// Iterate through all uu/ii turns (non-clustered)
@@ -326,13 +561,10 @@ private:
Geometry2 const& m_geometry2;
Turns& m_turns;
Clusters& m_clusters;
+ merge_map m_turns_per_ring;
+ region_connection_map m_connected_regions;
RobustPolicy const& m_robust_policy;
Visitor& m_visitor;
-
- std::map<ring_identifier, int> m_regions;
- std::map<ring_identifier, std::set<signed_size_type> > m_turns_per_ring;
- int m_region_id;
-
};
}} // namespace detail::overlay
diff --git a/boost/geometry/algorithms/detail/overlay/turn_info.hpp b/boost/geometry/algorithms/detail/overlay/turn_info.hpp
index e09af126c6..3a4c2e94a1 100644
--- a/boost/geometry/algorithms/detail/overlay/turn_info.hpp
+++ b/boost/geometry/algorithms/detail/overlay/turn_info.hpp
@@ -89,18 +89,24 @@ struct turn_info
Point point;
method_type method;
+ bool touch_only; // True in case of method touch(interior) and lines do not cross
signed_size_type cluster_id; // For multiple turns on same location, >= 0. Else -1
bool discarded;
- bool colocated;
+
+ // TODO: move this to enriched
+ bool colocated_ii; // Colocated with a ii turn (TODO: or a ix turn)
+ bool colocated_uu; // Colocated with a uu turn or a ux turn
bool switch_source; // For u/u turns which can either switch or not
Container operations;
inline turn_info()
: method(method_none)
+ , touch_only(false)
, cluster_id(-1)
, discarded(false)
- , colocated(false)
+ , colocated_ii(false)
+ , colocated_uu(false)
, switch_source(false)
{}
@@ -133,7 +139,6 @@ struct turn_info
return has(operation_blocked);
}
-
private :
inline bool has12(operation_type type1, operation_type type2) const
{
diff --git a/boost/geometry/algorithms/detail/partition.hpp b/boost/geometry/algorithms/detail/partition.hpp
index 12c6a54661..db134d548d 100644
--- a/boost/geometry/algorithms/detail/partition.hpp
+++ b/boost/geometry/algorithms/detail/partition.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2011-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2015, 2017.
// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates.
@@ -106,11 +107,11 @@ inline void expand_with_elements(Box& total, IteratorVector const& input,
// Match forward_range with itself
template <typename IteratorVector, typename VisitPolicy>
-inline void handle_one(IteratorVector const& input, VisitPolicy& visitor)
+inline bool handle_one(IteratorVector const& input, VisitPolicy& visitor)
{
- if (boost::size(input) == 0)
+ if (boost::empty(input))
{
- return;
+ return true;
}
typedef typename boost::range_iterator<IteratorVector const>::type it_type;
@@ -121,9 +122,14 @@ inline void handle_one(IteratorVector const& input, VisitPolicy& visitor)
it_type it2 = it1;
for (++it2; it2 != boost::end(input); ++it2)
{
- visitor.apply(**it1, **it2);
+ if (! visitor.apply(**it1, **it2))
+ {
+ return false; // interrupt
+ }
}
}
+
+ return true;
}
// Match forward range 1 with forward range 2
@@ -133,7 +139,7 @@ template
typename IteratorVector2,
typename VisitPolicy
>
-inline void handle_two(IteratorVector1 const& input1,
+inline bool handle_two(IteratorVector1 const& input1,
IteratorVector2 const& input2,
VisitPolicy& visitor)
{
@@ -147,9 +153,9 @@ inline void handle_two(IteratorVector1 const& input1,
IteratorVector2 const
>::type iterator_type2;
- if (boost::size(input1) == 0 || boost::size(input2) == 0)
+ if (boost::empty(input1) || boost::empty(input2))
{
- return;
+ return true;
}
for(iterator_type1 it1 = boost::begin(input1);
@@ -160,9 +166,14 @@ inline void handle_two(IteratorVector1 const& input1,
it2 != boost::end(input2);
++it2)
{
- visitor.apply(**it1, **it2);
+ if (! visitor.apply(**it1, **it2))
+ {
+ return false; // interrupt
+ }
}
}
+
+ return true;
}
template <typename IteratorVector>
@@ -223,7 +234,7 @@ class partition_one_range
typename OverlapsPolicy,
typename VisitBoxPolicy
>
- static inline void next_level(Box const& box,
+ static inline bool next_level(Box const& box,
IteratorVector const& input,
std::size_t level, std::size_t min_elements,
VisitPolicy& visitor,
@@ -233,7 +244,7 @@ class partition_one_range
{
if (recurse_ok(input, min_elements, level))
{
- partition_one_range
+ return partition_one_range
<
1 - Dimension,
Box
@@ -242,7 +253,7 @@ class partition_one_range
}
else
{
- handle_one(input, visitor);
+ return handle_one(input, visitor);
}
}
@@ -256,18 +267,18 @@ class partition_one_range
typename OverlapsPolicy,
typename VisitBoxPolicy
>
- static inline void next_level2(Box const& box,
- IteratorVector const& input1,
- IteratorVector const& input2,
- std::size_t level, std::size_t min_elements,
- VisitPolicy& visitor,
- ExpandPolicy const& expand_policy,
- OverlapsPolicy const& overlaps_policy,
- VisitBoxPolicy& box_policy)
+ static inline bool next_level2(Box const& box,
+ IteratorVector const& input1,
+ IteratorVector const& input2,
+ std::size_t level, std::size_t min_elements,
+ VisitPolicy& visitor,
+ ExpandPolicy const& expand_policy,
+ OverlapsPolicy const& overlaps_policy,
+ VisitBoxPolicy& box_policy)
{
if (recurse_ok(input1, input2, min_elements, level))
{
- partition_two_ranges
+ return partition_two_ranges
<
1 - Dimension, Box
>::apply(box, input1, input2, level + 1, min_elements,
@@ -276,7 +287,7 @@ class partition_one_range
}
else
{
- handle_two(input1, input2, visitor);
+ return handle_two(input1, input2, visitor);
}
}
@@ -289,7 +300,7 @@ public :
typename OverlapsPolicy,
typename VisitBoxPolicy
>
- static inline void apply(Box const& box,
+ static inline bool apply(Box const& box,
IteratorVector const& input,
std::size_t level,
std::size_t min_elements,
@@ -308,29 +319,31 @@ public :
input, lower, upper, exceeding,
overlaps_policy);
- if (boost::size(exceeding) > 0)
+ if (! boost::empty(exceeding))
{
// Get the box of exceeding-only
Box exceeding_box = get_new_box(exceeding, expand_policy);
- // Recursively do exceeding elements only, in next dimension they
- // will probably be less exceeding within the new box
- next_level(exceeding_box, exceeding, level, min_elements,
- visitor, expand_policy, overlaps_policy, box_policy);
-
- // Switch to two forward ranges, combine exceeding with
- // lower resp upper, but not lower/lower, upper/upper
- next_level2(exceeding_box, exceeding, lower, level, min_elements,
- visitor, expand_policy, overlaps_policy, box_policy);
- next_level2(exceeding_box, exceeding, upper, level, min_elements,
- visitor, expand_policy, overlaps_policy, box_policy);
+ // Recursively do exceeding elements only, in next dimension they
+ // will probably be less exceeding within the new box
+ if (! (next_level(exceeding_box, exceeding, level, min_elements,
+ visitor, expand_policy, overlaps_policy, box_policy)
+ // Switch to two forward ranges, combine exceeding with
+ // lower resp upper, but not lower/lower, upper/upper
+ && next_level2(exceeding_box, exceeding, lower, level, min_elements,
+ visitor, expand_policy, overlaps_policy, box_policy)
+ && next_level2(exceeding_box, exceeding, upper, level, min_elements,
+ visitor, expand_policy, overlaps_policy, box_policy)) )
+ {
+ return false; // interrupt
+ }
}
// Recursively call operation both parts
- next_level(lower_box, lower, level, min_elements,
- visitor, expand_policy, overlaps_policy, box_policy);
- next_level(upper_box, upper, level, min_elements,
- visitor, expand_policy, overlaps_policy, box_policy);
+ return next_level(lower_box, lower, level, min_elements,
+ visitor, expand_policy, overlaps_policy, box_policy)
+ && next_level(upper_box, upper, level, min_elements,
+ visitor, expand_policy, overlaps_policy, box_policy);
}
};
@@ -352,23 +365,23 @@ class partition_two_ranges
typename OverlapsPolicy2,
typename VisitBoxPolicy
>
- static inline void next_level(Box const& box,
- IteratorVector1 const& input1,
- IteratorVector2 const& input2,
- std::size_t level, std::size_t min_elements,
- VisitPolicy& visitor,
- ExpandPolicy1 const& expand_policy1,
- OverlapsPolicy1 const& overlaps_policy1,
- ExpandPolicy2 const& expand_policy2,
- OverlapsPolicy2 const& overlaps_policy2,
- VisitBoxPolicy& box_policy)
+ static inline bool next_level(Box const& box,
+ IteratorVector1 const& input1,
+ IteratorVector2 const& input2,
+ std::size_t level, std::size_t min_elements,
+ VisitPolicy& visitor,
+ ExpandPolicy1 const& expand_policy1,
+ OverlapsPolicy1 const& overlaps_policy1,
+ ExpandPolicy2 const& expand_policy2,
+ OverlapsPolicy2 const& overlaps_policy2,
+ VisitBoxPolicy& box_policy)
{
- partition_two_ranges
- <
- 1 - Dimension, Box
- >::apply(box, input1, input2, level + 1, min_elements,
- visitor, expand_policy1, overlaps_policy1,
- expand_policy2, overlaps_policy2, box_policy);
+ return partition_two_ranges
+ <
+ 1 - Dimension, Box
+ >::apply(box, input1, input2, level + 1, min_elements,
+ visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy);
}
template <typename IteratorVector, typename ExpandPolicy>
@@ -408,17 +421,17 @@ public :
typename OverlapsPolicy2,
typename VisitBoxPolicy
>
- static inline void apply(Box const& box,
- IteratorVector1 const& input1,
- IteratorVector2 const& input2,
- std::size_t level,
- std::size_t min_elements,
- VisitPolicy& visitor,
- ExpandPolicy1 const& expand_policy1,
- OverlapsPolicy1 const& overlaps_policy1,
- ExpandPolicy2 const& expand_policy2,
- OverlapsPolicy2 const& overlaps_policy2,
- VisitBoxPolicy& box_policy)
+ static inline bool apply(Box const& box,
+ IteratorVector1 const& input1,
+ IteratorVector2 const& input2,
+ std::size_t level,
+ std::size_t min_elements,
+ VisitPolicy& visitor,
+ ExpandPolicy1 const& expand_policy1,
+ OverlapsPolicy1 const& overlaps_policy1,
+ ExpandPolicy2 const& expand_policy2,
+ OverlapsPolicy2 const& overlaps_policy2,
+ VisitBoxPolicy& box_policy)
{
box_policy.apply(box, level);
@@ -434,7 +447,7 @@ public :
input2, lower2, upper2, exceeding2,
overlaps_policy2);
- if (boost::size(exceeding1) > 0)
+ if (! boost::empty(exceeding1))
{
// All exceeding from 1 with 2:
@@ -442,13 +455,19 @@ public :
{
Box exceeding_box = get_new_box(exceeding1, exceeding2,
expand_policy1, expand_policy2);
- next_level(exceeding_box, exceeding1, exceeding2, level,
- min_elements, visitor, expand_policy1, overlaps_policy1,
- expand_policy2, overlaps_policy2, box_policy);
+ if (! next_level(exceeding_box, exceeding1, exceeding2, level,
+ min_elements, visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy))
+ {
+ return false; // interrupt
+ }
}
else
{
- handle_two(exceeding1, exceeding2, visitor);
+ if (! handle_two(exceeding1, exceeding2, visitor))
+ {
+ return false; // interrupt
+ }
}
// All exceeding from 1 with lower and upper of 2:
@@ -458,60 +477,87 @@ public :
if (recurse_ok(lower2, upper2, exceeding1, min_elements, level))
{
Box exceeding_box = get_new_box(exceeding1, expand_policy1);
- next_level(exceeding_box, exceeding1, lower2, level,
- min_elements, visitor, expand_policy1, overlaps_policy1,
- expand_policy2, overlaps_policy2, box_policy);
- next_level(exceeding_box, exceeding1, upper2, level,
- min_elements, visitor, expand_policy1, overlaps_policy1,
- expand_policy2, overlaps_policy2, box_policy);
+ if (! (next_level(exceeding_box, exceeding1, lower2, level,
+ min_elements, visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy)
+ && next_level(exceeding_box, exceeding1, upper2, level,
+ min_elements, visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy)) )
+ {
+ return false; // interrupt
+ }
}
else
{
- handle_two(exceeding1, lower2, visitor);
- handle_two(exceeding1, upper2, visitor);
+ if (! (handle_two(exceeding1, lower2, visitor)
+ && handle_two(exceeding1, upper2, visitor)) )
+ {
+ return false; // interrupt
+ }
}
}
- if (boost::size(exceeding2) > 0)
+ if (! boost::empty(exceeding2))
{
// All exceeding from 2 with lower and upper of 1:
if (recurse_ok(lower1, upper1, exceeding2, min_elements, level))
{
Box exceeding_box = get_new_box(exceeding2, expand_policy2);
- next_level(exceeding_box, lower1, exceeding2, level,
- min_elements, visitor, expand_policy1, overlaps_policy1,
- expand_policy2, overlaps_policy2, box_policy);
- next_level(exceeding_box, upper1, exceeding2, level,
- min_elements, visitor, expand_policy1, overlaps_policy1,
- expand_policy2, overlaps_policy2, box_policy);
+ if (! (next_level(exceeding_box, lower1, exceeding2, level,
+ min_elements, visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy)
+ && next_level(exceeding_box, upper1, exceeding2, level,
+ min_elements, visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy)) )
+ {
+ return false; // interrupt
+ }
}
else
{
- handle_two(lower1, exceeding2, visitor);
- handle_two(upper1, exceeding2, visitor);
+ if (! (handle_two(lower1, exceeding2, visitor)
+ && handle_two(upper1, exceeding2, visitor)) )
+ {
+ return false; // interrupt
+ }
}
}
if (recurse_ok(lower1, lower2, min_elements, level))
{
- next_level(lower_box, lower1, lower2, level,
- min_elements, visitor, expand_policy1, overlaps_policy1,
- expand_policy2, overlaps_policy2, box_policy);
+ if (! next_level(lower_box, lower1, lower2, level,
+ min_elements, visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy) )
+ {
+ return false; // interrupt
+ }
}
else
{
- handle_two(lower1, lower2, visitor);
+ if (! handle_two(lower1, lower2, visitor))
+ {
+ return false; // interrupt
+ }
}
+
if (recurse_ok(upper1, upper2, min_elements, level))
{
- next_level(upper_box, upper1, upper2, level,
- min_elements, visitor, expand_policy1, overlaps_policy1,
- expand_policy2, overlaps_policy2, box_policy);
+ if (! next_level(upper_box, upper1, upper2, level,
+ min_elements, visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy) )
+ {
+ return false; // interrupt
+ }
}
else
{
- handle_two(upper1, upper2, visitor);
+ if (! handle_two(upper1, upper2, visitor))
+ {
+ return false; // interrupt
+ }
}
+
+ return true;
}
};
@@ -577,13 +623,13 @@ public:
typename ExpandPolicy,
typename OverlapsPolicy
>
- static inline void apply(ForwardRange const& forward_range,
+ static inline bool apply(ForwardRange const& forward_range,
VisitPolicy& visitor,
ExpandPolicy const& expand_policy,
OverlapsPolicy const& overlaps_policy)
{
- apply(forward_range, visitor, expand_policy, overlaps_policy,
- default_min_elements, detail::partition::visit_no_policy());
+ return apply(forward_range, visitor, expand_policy, overlaps_policy,
+ default_min_elements, detail::partition::visit_no_policy());
}
template
@@ -593,14 +639,14 @@ public:
typename ExpandPolicy,
typename OverlapsPolicy
>
- static inline void apply(ForwardRange const& forward_range,
+ static inline bool apply(ForwardRange const& forward_range,
VisitPolicy& visitor,
ExpandPolicy const& expand_policy,
OverlapsPolicy const& overlaps_policy,
std::size_t min_elements)
{
- apply(forward_range, visitor, expand_policy, overlaps_policy,
- min_elements, detail::partition::visit_no_policy());
+ return apply(forward_range, visitor, expand_policy, overlaps_policy,
+ min_elements, detail::partition::visit_no_policy());
}
template
@@ -611,7 +657,7 @@ public:
typename OverlapsPolicy,
typename VisitBoxPolicy
>
- static inline void apply(ForwardRange const& forward_range,
+ static inline bool apply(ForwardRange const& forward_range,
VisitPolicy& visitor,
ExpandPolicy const& expand_policy,
OverlapsPolicy const& overlaps_policy,
@@ -631,7 +677,7 @@ public:
expand_to_range<IncludePolicy1>(forward_range, total,
iterator_vector, expand_policy);
- detail::partition::partition_one_range
+ return detail::partition::partition_one_range
<
0, Box
>::apply(total, iterator_vector, 0, min_elements,
@@ -646,10 +692,15 @@ public:
iterator_type it2 = it1;
for(++it2; it2 != boost::end(forward_range); ++it2)
{
- visitor.apply(*it1, *it2);
+ if (! visitor.apply(*it1, *it2))
+ {
+ return false; // interrupt
+ }
}
}
}
+
+ return true;
}
template
@@ -660,15 +711,15 @@ public:
typename ExpandPolicy1,
typename OverlapsPolicy1
>
- static inline void apply(ForwardRange1 const& forward_range1,
+ static inline bool apply(ForwardRange1 const& forward_range1,
ForwardRange2 const& forward_range2,
VisitPolicy& visitor,
ExpandPolicy1 const& expand_policy1,
OverlapsPolicy1 const& overlaps_policy1)
{
- apply(forward_range1, forward_range2, visitor,
- expand_policy1, overlaps_policy1, expand_policy1, overlaps_policy1,
- default_min_elements, detail::partition::visit_no_policy());
+ return apply(forward_range1, forward_range2, visitor,
+ expand_policy1, overlaps_policy1, expand_policy1, overlaps_policy1,
+ default_min_elements, detail::partition::visit_no_policy());
}
template
@@ -681,7 +732,7 @@ public:
typename ExpandPolicy2,
typename OverlapsPolicy2
>
- static inline void apply(ForwardRange1 const& forward_range1,
+ static inline bool apply(ForwardRange1 const& forward_range1,
ForwardRange2 const& forward_range2,
VisitPolicy& visitor,
ExpandPolicy1 const& expand_policy1,
@@ -689,9 +740,9 @@ public:
ExpandPolicy2 const& expand_policy2,
OverlapsPolicy2 const& overlaps_policy2)
{
- apply(forward_range1, forward_range2, visitor,
- expand_policy1, overlaps_policy1, expand_policy2, overlaps_policy2,
- default_min_elements, detail::partition::visit_no_policy());
+ return apply(forward_range1, forward_range2, visitor,
+ expand_policy1, overlaps_policy1, expand_policy2, overlaps_policy2,
+ default_min_elements, detail::partition::visit_no_policy());
}
template
@@ -704,7 +755,7 @@ public:
typename ExpandPolicy2,
typename OverlapsPolicy2
>
- static inline void apply(ForwardRange1 const& forward_range1,
+ static inline bool apply(ForwardRange1 const& forward_range1,
ForwardRange2 const& forward_range2,
VisitPolicy& visitor,
ExpandPolicy1 const& expand_policy1,
@@ -713,9 +764,9 @@ public:
OverlapsPolicy2 const& overlaps_policy2,
std::size_t min_elements)
{
- apply(forward_range1, forward_range2, visitor,
- expand_policy1, overlaps_policy1, expand_policy2, overlaps_policy1,
- min_elements, detail::partition::visit_no_policy());
+ return apply(forward_range1, forward_range2, visitor,
+ expand_policy1, overlaps_policy1, expand_policy2, overlaps_policy1,
+ min_elements, detail::partition::visit_no_policy());
}
template
@@ -729,7 +780,7 @@ public:
typename OverlapsPolicy2,
typename VisitBoxPolicy
>
- static inline void apply(ForwardRange1 const& forward_range1,
+ static inline bool apply(ForwardRange1 const& forward_range1,
ForwardRange2 const& forward_range2,
VisitPolicy& visitor,
ExpandPolicy1 const& expand_policy1,
@@ -761,7 +812,7 @@ public:
expand_to_range<IncludePolicy2>(forward_range2, total,
iterator_vector2, expand_policy2);
- detail::partition::partition_two_ranges
+ return detail::partition::partition_two_ranges
<
0, Box
>::apply(total, iterator_vector1, iterator_vector2,
@@ -779,10 +830,15 @@ public:
it2 != boost::end(forward_range2);
++it2)
{
- visitor.apply(*it1, *it2);
+ if (! visitor.apply(*it1, *it2))
+ {
+ return false; // interrupt
+ }
}
}
}
+
+ return true;
}
};
diff --git a/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp b/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp
index 607ba81531..b8ea5e30e6 100644
--- a/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp
+++ b/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp
@@ -5,10 +5,11 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2017.
+// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -19,11 +20,13 @@
#include <boost/geometry/algorithms/detail/direction_code.hpp>
#include <boost/geometry/algorithms/detail/recalculate.hpp>
+#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
+
namespace boost { namespace geometry
{
@@ -32,6 +35,26 @@ namespace boost { namespace geometry
namespace detail
{
+template <typename Point1, typename Point2, typename Point3>
+inline bool collinear_point_is_spike_or_equal(Point1 const& last_point,
+ Point2 const& segment_a,
+ Point3 const& segment_b)
+{
+ // Check if segment is equal
+ int const sgn_x1 = sign_of_difference<0>(last_point, segment_b);
+ int const sgn_y1 = sign_of_difference<1>(last_point, segment_b);
+ if (sgn_x1 == 0 && sgn_y1 == 0)
+ {
+ return true;
+ }
+
+ // Check if segment moves forward
+ int const sgn_x2 = sign_of_difference<0>(segment_b, segment_a);
+ int const sgn_y2 = sign_of_difference<1>(segment_b, segment_a);
+
+ return sgn_x1 != sgn_x2 || sgn_y1 != sgn_y2;
+}
+
// Checks if a point ("last_point") causes a spike w.r.t.
// the specified two other points (segment_a, segment_b)
//
@@ -42,33 +65,29 @@ namespace detail
// So specify last point first, then (a,b)
// The segment's orientation does matter: if lp is to the right of b
// no spike is reported
-template <typename Point1, typename Point2, typename Point3>
-static inline bool point_is_spike_or_equal(Point1 const& last_point,
- Point2 const& segment_a,
- Point3 const& segment_b)
+template
+<
+ typename Point1, typename Point2, typename Point3,
+ typename SideStrategy
+>
+static inline bool point_is_spike_or_equal(Point1 const& last_point, // prev | back
+ Point2 const& segment_a, // next | back - 2
+ Point3 const& segment_b, // curr | back - 1 | spike's vertex
+ SideStrategy const& strategy)
{
- typedef typename strategy::side::services::default_strategy
- <
- typename cs_tag<Point1>::type
- >::type side_strategy;
-
- int const side = side_strategy::apply(last_point, segment_a, segment_b);
+ int const side = strategy.apply(segment_a, segment_b, last_point);
if (side == 0)
{
// Last point is collinear w.r.t previous segment.
- // Check if it is equal
- int const sgn_x1 = sign_of_difference<0>(last_point, segment_b);
- int const sgn_y1 = sign_of_difference<1>(last_point, segment_b);
- if (sgn_x1 == 0 && sgn_y1 == 0)
- {
- return true;
- }
-
- // Check if it moves forward
- int const sgn_x2 = sign_of_difference<0>(segment_b, segment_a);
- int const sgn_y2 = sign_of_difference<1>(segment_b, segment_a);
-
- return sgn_x1 != sgn_x2 || sgn_y1 != sgn_y2;
+#ifdef BOOST_GEOMETRY_ENABLE_POINT_IS_SPIKE_OR_EQUAL_TEST
+ bool r1 = collinear_point_is_spike_or_equal(last_point, segment_a, segment_b);
+ bool r2 = direction_code(segment_a, segment_b, last_point) < 1;
+ if (r1 != r2)
+ std::cout << "spike detection failure with: " << r1 << " " << r2 << std::endl;
+ return r2;
+#else
+ return direction_code(segment_a, segment_b, last_point) < 1;
+#endif
}
return false;
}
@@ -78,14 +97,16 @@ template
typename Point1,
typename Point2,
typename Point3,
+ typename SideStrategy,
typename RobustPolicy
>
static inline bool point_is_spike_or_equal(Point1 const& last_point,
Point2 const& segment_a,
Point3 const& segment_b,
+ SideStrategy const& strategy,
RobustPolicy const& robust_policy)
{
- if (point_is_spike_or_equal(last_point, segment_a, segment_b))
+ if (point_is_spike_or_equal(last_point, segment_a, segment_b, strategy))
{
return true;
}
@@ -111,7 +132,8 @@ static inline bool point_is_spike_or_equal(Point1 const& last_point,
(
last_point_rob,
segment_a_rob,
- segment_b_rob
+ segment_b_rob,
+ strategy
);
}
diff --git a/boost/geometry/algorithms/detail/point_on_border.hpp b/boost/geometry/algorithms/detail/point_on_border.hpp
index 1c751c23e4..831081aa69 100644
--- a/boost/geometry/algorithms/detail/point_on_border.hpp
+++ b/boost/geometry/algorithms/detail/point_on_border.hpp
@@ -4,6 +4,10 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -18,6 +22,7 @@
#include <cstddef>
#include <boost/range.hpp>
+#include <boost/static_assert.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/point_type.hpp>
@@ -29,6 +34,8 @@
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
+#include <boost/geometry/util/condition.hpp>
+
namespace boost { namespace geometry
{
@@ -39,10 +46,10 @@ namespace detail { namespace point_on_border
{
-template<typename Point>
struct get_point
{
- static inline bool apply(Point& destination, Point const& source, bool)
+ template <typename Point>
+ static inline bool apply(Point& destination, Point const& source)
{
destination = source;
return true;
@@ -74,66 +81,77 @@ struct midpoint_helper<Point, DimensionCount, DimensionCount>
};
-template<typename Point, typename Range>
+template <bool Midpoint>
struct point_on_range
{
- static inline bool apply(Point& point, Range const& range, bool midpoint)
+ // Version with iterator
+ template<typename Point, typename Iterator>
+ static inline bool apply(Point& point, Iterator begin, Iterator end)
{
- const std::size_t n = boost::size(range);
- if (midpoint && n > 1)
+ Iterator it = begin;
+ if (it == end)
{
- typedef typename boost::range_iterator
- <
- Range const
- >::type iterator;
-
- iterator it = boost::begin(range);
- iterator prev = it++;
- while (it != boost::end(range)
- && detail::equals::equals_point_point(*it, *prev))
- {
- prev = it++;
- }
- if (it != boost::end(range))
- {
- return midpoint_helper
- <
- Point,
- 0, dimension<Point>::value
- >::apply(point, *prev, *it);
- }
+ return false;
}
- if (n > 0)
+ if (! Midpoint)
{
- geometry::detail::conversion::convert_point_to_point(*boost::begin(range), point);
+ geometry::detail::conversion::convert_point_to_point(*it, point);
return true;
}
+
+ Iterator prev = it++;
+
+ // Go to next non-duplicate point
+ while (it != end
+ && detail::equals::equals_point_point(*it, *prev))
+ {
+ prev = it++;
+ }
+ if (it != end)
+ {
+ return midpoint_helper
+ <
+ Point,
+ 0, dimension<Point>::value
+ >::apply(point, *prev, *it);
+ }
return false;
}
+
+ // Version with range
+ template<typename Point, typename Range>
+ static inline bool apply(Point& point, Range const& range)
+ {
+ typedef typename geometry::cs_tag<Point>::type cs_tag;
+ BOOST_STATIC_ASSERT((! Midpoint || boost::is_same<cs_tag, cartesian_tag>::value));
+
+ return apply(point, boost::begin(range), boost::end(range));
+ }
};
-template<typename Point, typename Polygon>
+template <bool Midpoint>
struct point_on_polygon
{
- static inline bool apply(Point& point, Polygon const& polygon, bool midpoint)
+ template<typename Point, typename Polygon>
+ static inline bool apply(Point& point, Polygon const& polygon)
{
return point_on_range
<
- Point,
- typename ring_type<Polygon>::type
- >::apply(point, exterior_ring(polygon), midpoint);
+ Midpoint
+ >::apply(point, exterior_ring(polygon));
}
};
-template<typename Point, typename Box>
+template <bool Midpoint>
struct point_on_box
{
- static inline bool apply(Point& point, Box const& box, bool midpoint)
+ template<typename Point, typename Box>
+ static inline bool apply(Point& point, Box const& box)
{
- if (midpoint)
+ if (BOOST_GEOMETRY_CONDITION(Midpoint))
{
Point p1, p2;
detail::assign::assign_box_2d_corner<min_corner, min_corner>(box, p1);
@@ -154,15 +172,11 @@ struct point_on_box
};
-template
-<
- typename Point,
- typename MultiGeometry,
- typename Policy
->
+template <typename Policy>
struct point_on_multi
{
- static inline bool apply(Point& point, MultiGeometry const& multi, bool midpoint)
+ template<typename Point, typename MultiGeometry>
+ static inline bool apply(Point& point, MultiGeometry const& multi)
{
// Take a point on the first multi-geometry
// (i.e. the first that is not empty)
@@ -173,7 +187,7 @@ struct point_on_multi
it != boost::end(multi);
++it)
{
- if (Policy::apply(point, *it, midpoint))
+ if (Policy::apply(point, *it))
{
return true;
}
@@ -195,70 +209,57 @@ namespace dispatch
template
<
typename GeometryTag,
- typename Point,
- typename Geometry
+ bool Midpoint
>
struct point_on_border
{};
-template<typename Point>
-struct point_on_border<point_tag, Point, Point>
- : detail::point_on_border::get_point<Point>
+template <bool Midpoint>
+struct point_on_border<point_tag, Midpoint>
+ : detail::point_on_border::get_point
{};
-template<typename Point, typename Linestring>
-struct point_on_border<linestring_tag, Point, Linestring>
- : detail::point_on_border::point_on_range<Point, Linestring>
+template <bool Midpoint>
+struct point_on_border<linestring_tag, Midpoint>
+ : detail::point_on_border::point_on_range<Midpoint>
{};
-template<typename Point, typename Ring>
-struct point_on_border<ring_tag, Point, Ring>
- : detail::point_on_border::point_on_range<Point, Ring>
+template <bool Midpoint>
+struct point_on_border<ring_tag, Midpoint>
+ : detail::point_on_border::point_on_range<Midpoint>
{};
-template<typename Point, typename Polygon>
-struct point_on_border<polygon_tag, Point, Polygon>
- : detail::point_on_border::point_on_polygon<Point, Polygon>
+template <bool Midpoint>
+struct point_on_border<polygon_tag, Midpoint>
+ : detail::point_on_border::point_on_polygon<Midpoint>
{};
-template<typename Point, typename Box>
-struct point_on_border<box_tag, Point, Box>
- : detail::point_on_border::point_on_box<Point, Box>
+template <bool Midpoint>
+struct point_on_border<box_tag, Midpoint>
+ : detail::point_on_border::point_on_box<Midpoint>
{};
-template<typename Point, typename Multi>
-struct point_on_border<multi_polygon_tag, Point, Multi>
+template <bool Midpoint>
+struct point_on_border<multi_polygon_tag, Midpoint>
: detail::point_on_border::point_on_multi
<
- Point,
- Multi,
- detail::point_on_border::point_on_polygon
- <
- Point,
- typename boost::range_value<Multi>::type
- >
+ detail::point_on_border::point_on_polygon<Midpoint>
>
{};
-template<typename Point, typename Multi>
-struct point_on_border<multi_linestring_tag, Point, Multi>
+template <bool Midpoint>
+struct point_on_border<multi_linestring_tag, Midpoint>
: detail::point_on_border::point_on_multi
<
- Point,
- Multi,
- detail::point_on_border::point_on_range
- <
- Point,
- typename boost::range_value<Multi>::type
- >
+ detail::point_on_border::point_on_range<Midpoint>
>
{};
@@ -273,18 +274,12 @@ struct point_on_border<multi_linestring_tag, Point, Multi>
\tparam Geometry geometry type. This also defines the type of the output point
\param point to assign
\param geometry geometry to take point from
-\param midpoint boolean flag, true if the point should not be a vertex, but some point
- in between of two vertices
\return TRUE if successful, else false.
It is only false if polygon/line have no points
\note for a polygon, it is always a point on the exterior ring
-\note for take_midpoint, it is not taken from two consecutive duplicate vertices,
- (unless there are no other).
*/
template <typename Point, typename Geometry>
-inline bool point_on_border(Point& point,
- Geometry const& geometry,
- bool midpoint = false)
+inline bool point_on_border(Point& point, Geometry const& geometry)
{
concepts::check<Point>();
concepts::check<Geometry const>();
@@ -292,12 +287,32 @@ inline bool point_on_border(Point& point,
return dispatch::point_on_border
<
typename tag<Geometry>::type,
- Point,
- Geometry
- >::apply(point, geometry, midpoint);
+ false
+ >::apply(point, geometry);
}
+/*!
+\tparam Midpoint boolean flag, true if the point should not be a vertex, but some point
+ in between of two vertices
+\note for Midpoint, it is not taken from two consecutive duplicate vertices,
+ (unless there are no other).
+ */
+/*
+template <bool Midpoint, typename Point, typename Geometry>
+inline bool point_on_border(Point& point, Geometry const& geometry)
+{
+ concepts::check<Point>();
+ concepts::check<Geometry const>();
+
+ return dispatch::point_on_border
+ <
+ typename tag<Geometry>::type,
+ Midpoint
+ >::apply(point, geometry);
+}
+*/
+
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/relate/implementation.hpp b/boost/geometry/algorithms/detail/relate/implementation.hpp
index 3bd0f806c1..8f7942d46e 100644
--- a/boost/geometry/algorithms/detail/relate/implementation.hpp
+++ b/boost/geometry/algorithms/detail/relate/implementation.hpp
@@ -23,6 +23,7 @@
#include <boost/geometry/algorithms/detail/relate/point_geometry.hpp>
#include <boost/geometry/algorithms/detail/relate/linear_linear.hpp>
#include <boost/geometry/algorithms/detail/relate/linear_areal.hpp>
+#include <boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp>
#include <boost/geometry/algorithms/detail/relate/areal_areal.hpp>
#include <boost/geometry/strategies/intersection.hpp>
@@ -81,6 +82,16 @@ struct relate<Geometry, Point, Tag1, point_tag, TopDim1, 0, true>
: detail::relate::geometry_point<Geometry, Point>
{};
+template <typename MultiPoint, typename Geometry, typename Tag2, int TopDim2>
+struct relate<MultiPoint, Geometry, multi_point_tag, Tag2, 0, TopDim2, false>
+ : detail::relate::multi_point_geometry<MultiPoint, Geometry>
+{};
+
+template <typename Geometry, typename MultiPoint, typename Tag1, int TopDim1>
+struct relate<Geometry, MultiPoint, Tag1, multi_point_tag, TopDim1, 0, false>
+ : detail::relate::geometry_multi_point<Geometry, MultiPoint>
+{};
+
template <typename Linear1, typename Linear2, typename Tag1, typename Tag2>
struct relate<Linear1, Linear2, Tag1, Tag2, 1, 1, true>
diff --git a/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp b/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp
new file mode 100644
index 0000000000..47c6963b87
--- /dev/null
+++ b/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp
@@ -0,0 +1,568 @@
+// Boost.Geometry
+
+// Copyright (c) 2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the 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_GEOMETRY_ALGORITHMS_DETAIL_RELATE_MULTI_POINT_GEOMETRY_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_MULTI_POINT_GEOMETRY_HPP
+
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
+#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
+#include <boost/geometry/algorithms/detail/relate/result.hpp>
+#include <boost/geometry/algorithms/detail/relate/topology_check.hpp>
+#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
+#include <boost/geometry/algorithms/envelope.hpp>
+
+#include <boost/geometry/core/is_areal.hpp>
+#include <boost/geometry/core/point_type.hpp>
+
+#include <boost/geometry/geometries/box.hpp>
+
+#include <boost/geometry/index/rtree.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace relate
+{
+
+template
+<
+ typename Geometry,
+ typename Tag = typename tag<Geometry>::type
+>
+struct multi_point_geometry_eb
+{
+ template <typename MultiPoint>
+ static inline bool apply(MultiPoint const& ,
+ detail::relate::topology_check<Geometry> const& )
+ {
+ return true;
+ }
+};
+
+template <typename Geometry>
+struct multi_point_geometry_eb<Geometry, linestring_tag>
+{
+ template <typename Points>
+ struct boundary_visitor
+ {
+ boundary_visitor(Points const& points)
+ : m_points(points)
+ , m_boundary_found(false)
+ {}
+
+ template <typename Point>
+ struct find_pred
+ {
+ find_pred(Point const& point)
+ : m_point(point)
+ {}
+
+ template <typename Pt>
+ bool operator()(Pt const& pt) const
+ {
+ return detail::equals::equals_point_point(pt, m_point);
+ }
+
+ Point const& m_point;
+ };
+
+ template <typename Point>
+ bool apply(Point const& boundary_point)
+ {
+ if (std::find_if(m_points.begin(), m_points.end(), find_pred<Point>(boundary_point)) == m_points.end())
+ {
+ m_boundary_found = true;
+ return false;
+ }
+ return true;
+ }
+
+ bool result() const { return m_boundary_found; }
+
+ private:
+ Points const& m_points;
+ bool m_boundary_found;
+ };
+
+ template <typename MultiPoint>
+ static inline bool apply(MultiPoint const& multi_point,
+ detail::relate::topology_check<Geometry> const& tc)
+ {
+ boundary_visitor<MultiPoint> visitor(multi_point);
+ tc.for_each_boundary_point(visitor);
+ return visitor.result();
+ }
+};
+
+template <typename Geometry>
+struct multi_point_geometry_eb<Geometry, multi_linestring_tag>
+{
+ template <typename Points>
+ struct boundary_visitor
+ {
+ boundary_visitor(Points const& points)
+ : m_points(points)
+ , m_boundary_found(false)
+ {}
+
+ template <typename Point>
+ bool apply(Point const& boundary_point)
+ {
+ if (! std::binary_search(m_points.begin(), m_points.end(), boundary_point, relate::less()))
+ {
+ m_boundary_found = true;
+ return false;
+ }
+ return true;
+ }
+
+ bool result() const { return m_boundary_found; }
+
+ private:
+ Points const& m_points;
+ bool m_boundary_found;
+ };
+
+ template <typename MultiPoint>
+ static inline bool apply(MultiPoint const& multi_point,
+ detail::relate::topology_check<Geometry> const& tc)
+ {
+ typedef typename boost::range_value<MultiPoint>::type point_type;
+ typedef std::vector<point_type> points_type;
+ points_type points(boost::begin(multi_point), boost::end(multi_point));
+ std::sort(points.begin(), points.end(), relate::less());
+
+ boundary_visitor<points_type> visitor(points);
+ tc.for_each_boundary_point(visitor);
+ return visitor.result();
+ }
+};
+
+// SingleGeometry - Linear or Areal
+template <typename MultiPoint, typename SingleGeometry, bool Transpose = false>
+struct multi_point_single_geometry
+{
+ static const bool interruption_enabled = true;
+
+ template <typename Result, typename Strategy>
+ static inline void apply(MultiPoint const& multi_point,
+ SingleGeometry const& single_geometry,
+ Result & result,
+ Strategy const& strategy)
+ {
+ typedef typename point_type<SingleGeometry>::type point2_type;
+ typedef model::box<point2_type> box2_type;
+
+ box2_type box2;
+ geometry::envelope(single_geometry, box2, strategy.get_envelope_strategy());
+ geometry::detail::expand_by_epsilon(box2);
+
+ typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
+ for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
+ {
+ if (! (relate::may_update<interior, interior, '0', Transpose>(result)
+ || relate::may_update<interior, boundary, '0', Transpose>(result)
+ || relate::may_update<interior, exterior, '0', Transpose>(result) ) )
+ {
+ break;
+ }
+
+ // The default strategy is enough for Point/Box
+ if (detail::disjoint::disjoint_point_box(*it, box2))
+ {
+ relate::set<interior, exterior, '0', Transpose>(result);
+ }
+ else
+ {
+ int in_val = detail::within::point_in_geometry(*it, single_geometry, strategy);
+
+ if (in_val > 0) // within
+ {
+ relate::set<interior, interior, '0', Transpose>(result);
+ }
+ else if (in_val == 0)
+ {
+ relate::set<interior, boundary, '0', Transpose>(result);
+ }
+ else // in_val < 0 - not within
+ {
+ relate::set<interior, exterior, '0', Transpose>(result);
+ }
+ }
+
+ if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
+ {
+ return;
+ }
+ }
+
+ typedef detail::relate::topology_check<SingleGeometry> tc_t;
+ if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result)
+ || relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result) )
+ {
+ tc_t tc(single_geometry);
+
+ if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result)
+ && tc.has_interior() )
+ {
+ // TODO: this is not true if a linestring is degenerated to a point
+ // then the interior has topological dimension = 0, not 1
+ relate::set<exterior, interior, tc_t::interior, Transpose>(result);
+ }
+
+ if ( relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result)
+ && tc.has_boundary() )
+ {
+ if (multi_point_geometry_eb<SingleGeometry>::apply(multi_point, tc))
+ relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
+ }
+ }
+
+ relate::set<exterior, exterior, result_dimension<MultiPoint>::value, Transpose>(result);
+ }
+};
+
+
+// MultiGeometry - Linear or Areal
+// part of the algorithm calculating II and IB when no IE has to be calculated
+// using partition()
+template <typename MultiPoint, typename MultiGeometry, bool Transpose>
+class multi_point_multi_geometry_ii_ib
+{
+ struct expand_box_point
+ {
+ template <typename Box, typename Point>
+ static inline void apply(Box& total, Point const& point)
+ {
+ geometry::expand(total, point);
+ }
+ };
+
+ struct expand_box_box_pair
+ {
+ template <typename Box, typename BoxPair>
+ static inline void apply(Box& total, BoxPair const& box_pair)
+ {
+ geometry::expand(total, box_pair.first);
+ }
+ };
+
+ struct overlaps_box_point
+ {
+ template <typename Box, typename Point>
+ static inline bool apply(Box const& box, Point const& point)
+ {
+ // The default strategy is enough for Point/Box
+ return ! detail::disjoint::disjoint_point_box(point, box);
+ }
+ };
+
+ struct overlaps_box_box_pair
+ {
+ template <typename Box, typename BoxPair>
+ static inline bool apply(Box const& box, BoxPair const& box_pair)
+ {
+ // The default strategy is enough for Box/Box
+ return ! detail::disjoint::disjoint_box_box(box_pair.first, box);
+ }
+ };
+
+ template <typename Result, typename PtSegStrategy>
+ class item_visitor_type
+ {
+ public:
+ item_visitor_type(MultiGeometry const& multi_geometry,
+ detail::relate::topology_check<MultiGeometry> const& tc,
+ Result & result,
+ PtSegStrategy const& strategy)
+ : m_multi_geometry(multi_geometry)
+ , m_tc(tc)
+ , m_result(result)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Point, typename BoxPair>
+ inline bool apply(Point const& point, BoxPair const& box_pair)
+ {
+ // The default strategy is enough for Point/Box
+ if (! detail::disjoint::disjoint_point_box(point, box_pair.first))
+ {
+ typename boost::range_value<MultiGeometry>::type const&
+ single = range::at(m_multi_geometry, box_pair.second);
+
+ int in_val = detail::within::point_in_geometry(point, single, m_strategy);
+
+ if (in_val > 0) // within
+ {
+ relate::set<interior, interior, '0', Transpose>(m_result);
+ }
+ else if (in_val == 0)
+ {
+ if (m_tc.check_boundary_point(point))
+ relate::set<interior, boundary, '0', Transpose>(m_result);
+ else
+ relate::set<interior, interior, '0', Transpose>(m_result);
+ }
+ }
+
+ if ( BOOST_GEOMETRY_CONDITION(m_result.interrupt) )
+ {
+ return false;
+ }
+
+ if (! (relate::may_update<interior, interior, '0', Transpose>(m_result)
+ || relate::may_update<interior, boundary, '0', Transpose>(m_result) ) )
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+
+ private:
+ MultiGeometry const& m_multi_geometry;
+ detail::relate::topology_check<MultiGeometry> const& m_tc;
+ Result & m_result;
+ PtSegStrategy const& m_strategy;
+ };
+
+public:
+ typedef typename point_type<MultiPoint>::type point1_type;
+ typedef typename point_type<MultiGeometry>::type point2_type;
+ typedef model::box<point1_type> box1_type;
+ typedef model::box<point2_type> box2_type;
+ typedef std::pair<box2_type, std::size_t> box_pair_type;
+
+ template <typename Result, typename Strategy>
+ static inline void apply(MultiPoint const& multi_point,
+ MultiGeometry const& multi_geometry,
+ std::vector<box_pair_type> const& boxes,
+ detail::relate::topology_check<MultiGeometry> const& tc,
+ Result & result,
+ Strategy const& strategy)
+ {
+ item_visitor_type<Result, Strategy> visitor(multi_geometry, tc, result, strategy);
+
+ geometry::partition
+ <
+ box1_type
+ >::apply(multi_point, boxes, visitor,
+ expand_box_point(),
+ overlaps_box_point(),
+ expand_box_box_pair(),
+ overlaps_box_box_pair());
+ }
+
+};
+
+// MultiGeometry - Linear or Areal
+// part of the algorithm calculating II, IB and IE
+// using rtree
+template <typename MultiPoint, typename MultiGeometry, bool Transpose>
+struct multi_point_multi_geometry_ii_ib_ie
+{
+ typedef typename point_type<MultiPoint>::type point1_type;
+ typedef typename point_type<MultiGeometry>::type point2_type;
+ typedef model::box<point1_type> box1_type;
+ typedef model::box<point2_type> box2_type;
+ typedef std::pair<box2_type, std::size_t> box_pair_type;
+ typedef std::vector<box_pair_type> boxes_type;
+ typedef typename boxes_type::const_iterator boxes_iterator;
+
+ template <typename Result, typename Strategy>
+ static inline void apply(MultiPoint const& multi_point,
+ MultiGeometry const& multi_geometry,
+ std::vector<box_pair_type> const& boxes,
+ detail::relate::topology_check<MultiGeometry> const& tc,
+ Result & result,
+ Strategy const& strategy)
+ {
+ index::rtree<box_pair_type, index::rstar<4> > rt(boxes.begin(), boxes.end());
+
+ typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
+ for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
+ {
+ if (! (relate::may_update<interior, interior, '0', Transpose>(result)
+ || relate::may_update<interior, boundary, '0', Transpose>(result)
+ || relate::may_update<interior, exterior, '0', Transpose>(result) ) )
+ {
+ return;
+ }
+
+ typename boost::range_value<MultiPoint>::type const& point = *it;
+
+ boxes_type boxes_found;
+ rt.query(index::intersects(point), std::back_inserter(boxes_found));
+
+ bool found_ii_or_ib = false;
+ for (boxes_iterator bi = boxes_found.begin() ; bi != boxes_found.end() ; ++bi)
+ {
+ typename boost::range_value<MultiGeometry>::type const&
+ single = range::at(multi_geometry, bi->second);
+
+ int in_val = detail::within::point_in_geometry(point, single, strategy);
+
+ if (in_val > 0) // within
+ {
+ relate::set<interior, interior, '0', Transpose>(result);
+ found_ii_or_ib = true;
+ }
+ else if (in_val == 0) // on boundary of single
+ {
+ if (tc.check_boundary_point(point))
+ relate::set<interior, boundary, '0', Transpose>(result);
+ else
+ relate::set<interior, interior, '0', Transpose>(result);
+ found_ii_or_ib = true;
+ }
+ }
+
+ // neither interior nor boundary found -> exterior
+ if (found_ii_or_ib == false)
+ {
+ relate::set<interior, exterior, '0', Transpose>(result);
+ }
+
+ if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
+ {
+ return;
+ }
+ }
+ }
+};
+
+// MultiGeometry - Linear or Areal
+template <typename MultiPoint, typename MultiGeometry, bool Transpose = false>
+struct multi_point_multi_geometry
+{
+ static const bool interruption_enabled = true;
+
+ template <typename Result, typename Strategy>
+ static inline void apply(MultiPoint const& multi_point,
+ MultiGeometry const& multi_geometry,
+ Result & result,
+ Strategy const& strategy)
+ {
+ typedef typename point_type<MultiGeometry>::type point2_type;
+ typedef model::box<point2_type> box2_type;
+ typedef std::pair<box2_type, std::size_t> box_pair_type;
+
+ typename Strategy::envelope_strategy_type const
+ envelope_strategy = strategy.get_envelope_strategy();
+
+ std::size_t count2 = boost::size(multi_geometry);
+ std::vector<box_pair_type> boxes(count2);
+ for (std::size_t i = 0 ; i < count2 ; ++i)
+ {
+ geometry::envelope(range::at(multi_geometry, i), boxes[i].first, envelope_strategy);
+ geometry::detail::expand_by_epsilon(boxes[i].first);
+ boxes[i].second = i;
+ }
+
+ typedef detail::relate::topology_check<MultiGeometry> tc_t;
+ tc_t tc(multi_geometry);
+
+ if ( relate::may_update<interior, interior, '0', Transpose>(result)
+ || relate::may_update<interior, boundary, '0', Transpose>(result)
+ || relate::may_update<interior, exterior, '0', Transpose>(result) )
+ {
+ // If there is no need to calculate IE, use partition
+ if (! relate::may_update<interior, exterior, '0', Transpose>(result) )
+ {
+ multi_point_multi_geometry_ii_ib<MultiPoint, MultiGeometry, Transpose>
+ ::apply(multi_point, multi_geometry, boxes, tc, result, strategy);
+ }
+ else // otherwise use rtree
+ {
+ multi_point_multi_geometry_ii_ib_ie<MultiPoint, MultiGeometry, Transpose>
+ ::apply(multi_point, multi_geometry, boxes, tc, result, strategy);
+ }
+ }
+
+ if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
+ {
+ return;
+ }
+
+ if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result)
+ || relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result) )
+ {
+ if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result)
+ && tc.has_interior() )
+ {
+ // TODO: this is not true if a linestring is degenerated to a point
+ // then the interior has topological dimension = 0, not 1
+ relate::set<exterior, interior, tc_t::interior, Transpose>(result);
+ }
+
+ if ( relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result)
+ && tc.has_boundary() )
+ {
+ if (multi_point_geometry_eb<MultiGeometry>::apply(multi_point, tc))
+ relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
+ }
+ }
+
+ relate::set<exterior, exterior, result_dimension<MultiPoint>::value, Transpose>(result);
+ }
+
+};
+
+
+template
+<
+ typename MultiPoint, typename Geometry,
+ bool Transpose = false,
+ bool isMulti = boost::is_same
+ <
+ typename tag_cast
+ <
+ typename tag<Geometry>::type, multi_tag
+ >::type,
+ multi_tag
+ >::value
+>
+struct multi_point_geometry
+ : multi_point_single_geometry<MultiPoint, Geometry, Transpose>
+{};
+
+template <typename MultiPoint, typename Geometry, bool Transpose>
+struct multi_point_geometry<MultiPoint, Geometry, Transpose, true>
+ : multi_point_multi_geometry<MultiPoint, Geometry, Transpose>
+{};
+
+
+// transposed result of multi_point_geometry
+template <typename Geometry, typename MultiPoint>
+struct geometry_multi_point
+{
+ static const bool interruption_enabled = true;
+
+ template <typename Result, typename Strategy>
+ static inline void apply(Geometry const& geometry, MultiPoint const& multi_point,
+ Result & result, Strategy const& strategy)
+ {
+ multi_point_geometry<MultiPoint, Geometry, true>::apply(multi_point, geometry, result, strategy);
+ }
+};
+
+}} // namespace detail::relate
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_MULTI_POINT_GEOMETRY_HPP
diff --git a/boost/geometry/algorithms/detail/relate/point_geometry.hpp b/boost/geometry/algorithms/detail/relate/point_geometry.hpp
index a0c6c0d49b..e78a404b21 100644
--- a/boost/geometry/algorithms/detail/relate/point_geometry.hpp
+++ b/boost/geometry/algorithms/detail/relate/point_geometry.hpp
@@ -60,29 +60,27 @@ struct point_geometry
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
- // the point is on the boundary
- if ( pig == 0 )
+ typedef detail::relate::topology_check<Geometry> tc_t;
+ if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result)
+ || relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result) )
{
- // NOTE: even for MLs, if there is at least one boundary point,
- // somewhere there must be another one
-
- // check if there are other boundaries outside
- typedef detail::relate::topology_check<Geometry> tc_t;
- //tc_t tc(geometry, point);
- //if ( tc.has_interior )
- relate::set<exterior, interior, tc_t::interior, Transpose>(result);
- //if ( tc.has_boundary )
- relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
- }
- else
- {
- // check if there is a boundary in Geometry
- typedef detail::relate::topology_check<Geometry> tc_t;
- tc_t tc(geometry);
- if ( tc.has_interior )
+ // the point is on the boundary
+ if ( pig == 0 )
+ {
+ // NOTE: even for MLs, if there is at least one boundary point,
+ // somewhere there must be another one
relate::set<exterior, interior, tc_t::interior, Transpose>(result);
- if ( tc.has_boundary )
relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
+ }
+ else
+ {
+ // check if there is a boundary in Geometry
+ tc_t tc(geometry);
+ if ( tc.has_interior() )
+ relate::set<exterior, interior, tc_t::interior, Transpose>(result);
+ if ( tc.has_boundary() )
+ relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
+ }
}
}
};
diff --git a/boost/geometry/algorithms/detail/relate/point_point.hpp b/boost/geometry/algorithms/detail/relate/point_point.hpp
index b41d346f0b..68d8be031e 100644
--- a/boost/geometry/algorithms/detail/relate/point_point.hpp
+++ b/boost/geometry/algorithms/detail/relate/point_point.hpp
@@ -165,22 +165,41 @@ struct multipoint_multipoint
}
}
-// TODO: ADD A CHECK TO THE RESULT INDICATING IF THE FIRST AND/OR SECOND GEOMETRY MUST BE ANALYSED
+ // The geometry containing smaller number of points will be analysed first
+ if ( boost::size(multi_point1) < boost::size(multi_point2) )
+ {
+ search_both<false>(multi_point1, multi_point2, result);
+ }
+ else
+ {
+ search_both<true>(multi_point2, multi_point1, result);
+ }
-// TODO: if I/I is set for one MPt, this won't be changed when the other one in analysed
-// so if e.g. only I/I must be analysed we musn't check the other MPt
+ relate::set<exterior, exterior, result_dimension<MultiPoint1>::value>(result);
+ }
-// TODO: Also, the geometry with the smaller number of points may be analysed first
- //if ( boost::size(multi_point1) < boost::size(multi_point2) )
+ template <bool Transpose, typename MPt1, typename MPt2, typename Result>
+ static inline void search_both(MPt1 const& first_sorted_mpt, MPt2 const& first_iterated_mpt,
+ Result & result)
+ {
+ if ( relate::may_update<interior, interior, '0'>(result)
+ || relate::may_update<interior, exterior, '0'>(result)
+ || relate::may_update<exterior, interior, '0'>(result) )
+ {
+ // NlogN + MlogN
+ bool is_disjoint = search<Transpose>(first_sorted_mpt, first_iterated_mpt, result);
- // NlogN + MlogN
- bool all_handled = search<false>(multi_point1, multi_point2, result);
-
- if ( BOOST_GEOMETRY_CONDITION(all_handled || result.interrupt) )
- return;
+ if ( BOOST_GEOMETRY_CONDITION(is_disjoint || result.interrupt) )
+ return;
+ }
- // MlogM + NlogM
- search<true>(multi_point2, multi_point1, result);
+ if ( relate::may_update<interior, interior, '0'>(result)
+ || relate::may_update<interior, exterior, '0'>(result)
+ || relate::may_update<exterior, interior, '0'>(result) )
+ {
+ // MlogM + NlogM
+ search<! Transpose>(first_iterated_mpt, first_sorted_mpt, result);
+ }
}
template <bool Transpose,
@@ -215,9 +234,6 @@ struct multipoint_multipoint
break;
}
- // an optimization
- bool all_handled = false;
-
if ( found_inside ) // some point of MP2 is equal to some of MP1
{
// TODO: if I/I is set for one MPt, this won't be changed when the other one in analysed
@@ -234,14 +250,10 @@ struct multipoint_multipoint
{
relate::set<interior, exterior, '0', Transpose>(result);
relate::set<exterior, interior, '0', Transpose>(result);
-
- // if no point is intersecting the other MPt then we musn't analyse the reversed case
- all_handled = true;
}
- relate::set<exterior, exterior, result_dimension<point_type>::value, Transpose>(result);
-
- return all_handled;
+ // if no point is intersecting the other MPt then we musn't analyse the reversed case
+ return ! found_inside;
}
};
diff --git a/boost/geometry/algorithms/detail/relate/topology_check.hpp b/boost/geometry/algorithms/detail/relate/topology_check.hpp
index caa8a3c22d..654999d8fb 100644
--- a/boost/geometry/algorithms/detail/relate/topology_check.hpp
+++ b/boost/geometry/algorithms/detail/relate/topology_check.hpp
@@ -1,22 +1,23 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, Oracle and/or its affiliates.
+// Copyright (c) 2014-2017, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TOPOLOGY_CHECK_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TOPOLOGY_CHECK_HPP
-#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
-#include <boost/geometry/policies/compare.hpp>
+#include <boost/geometry/algorithms/detail/relate/less.hpp>
#include <boost/geometry/util/has_nan_coordinate.hpp>
+#include <boost/geometry/util/range.hpp>
+
namespace boost { namespace geometry {
@@ -51,31 +52,63 @@ struct topology_check<Linestring, linestring_tag>
static const char interior = '1';
static const char boundary = '0';
- bool has_interior;
- bool has_boundary;
-
topology_check(Linestring const& ls)
+ : m_ls(ls)
+ , m_is_initialized(false)
+ {}
+
+ bool has_interior() const
{
- init(ls, 0); /*dummy param*/
+ init();
+ return m_has_interior;
}
- template <typename IgnoreBoundaryPoint>
- topology_check(Linestring const& ls, IgnoreBoundaryPoint const& ibp)
+ bool has_boundary() const
{
- init(ls, ibp); /*dummy param, won't be used*/
+ init();
+ return m_has_boundary;
}
- // Even if some point is on the boundary, if the Linestring has the boundary,
- // there will be second boundary point different than IgnoreBoundaryPoint
- template <typename IgnoreBoundaryPoint>
- void init(Linestring const& ls, IgnoreBoundaryPoint const&)
+ /*template <typename Point>
+ bool check_boundary_point(Point const& point) const
{
- std::size_t count = boost::size(ls);
- has_interior = count > 0;
+ init();
+ return m_has_boundary
+ && ( equals::equals_point_point(point, range::front(m_ls))
+ || equals::equals_point_point(point, range::back(m_ls)) );
+ }*/
+
+ template <typename Visitor>
+ void for_each_boundary_point(Visitor & visitor) const
+ {
+ init();
+ if (m_has_boundary)
+ {
+ if (visitor.apply(range::front(m_ls)))
+ visitor.apply(range::back(m_ls));
+ }
+ }
+
+private:
+ void init() const
+ {
+ if (m_is_initialized)
+ return;
+
+ std::size_t count = boost::size(m_ls);
+ m_has_interior = count > 0;
// NOTE: Linestring with all points equal is treated as 1d linear ring
- has_boundary = count > 1
- && ! detail::equals::equals_point_point(range::front(ls), range::back(ls));
+ m_has_boundary = count > 1
+ && ! detail::equals::equals_point_point(range::front(m_ls), range::back(m_ls));
+
+ m_is_initialized = true;
}
+
+ Linestring const& m_ls;
+ mutable bool m_is_initialized;
+
+ mutable bool m_has_interior;
+ mutable bool m_has_boundary;
};
template <typename MultiLinestring>
@@ -84,29 +117,58 @@ struct topology_check<MultiLinestring, multi_linestring_tag>
static const char interior = '1';
static const char boundary = '0';
- bool has_interior;
- bool has_boundary;
-
topology_check(MultiLinestring const& mls)
+ : m_mls(mls)
+ , m_is_initialized(false)
+ {}
+
+ bool has_interior() const
{
- init(mls, not_ignoring_counter());
+ init();
+ return m_has_interior;
}
- template <typename IgnoreBoundaryPoint>
- topology_check(MultiLinestring const& mls, IgnoreBoundaryPoint const& ibp)
+ bool has_boundary() const
{
- init(mls, ignoring_counter<IgnoreBoundaryPoint>(ibp));
+ init();
+ return m_has_boundary;
}
- template <typename OddCounter>
- void init(MultiLinestring const& mls, OddCounter const& odd_counter)
+ template <typename Point>
+ bool check_boundary_point(Point const& point) const
{
- typedef typename geometry::point_type<MultiLinestring>::type point_type;
- std::vector<point_type> endpoints;
- endpoints.reserve(boost::size(mls) * 2);
+ init();
+
+ if (! m_has_boundary)
+ return false;
+
+ std::size_t count = count_equal(m_endpoints.begin(), m_endpoints.end(), point);
+
+ return count % 2 != 0; // odd count -> boundary
+ }
+
+ template <typename Visitor>
+ void for_each_boundary_point(Visitor & visitor) const
+ {
+ init();
+ if (m_has_boundary)
+ {
+ for_each_boundary_point(m_endpoints.begin(), m_endpoints.end(), visitor);
+ }
+ }
+
+private:
+ void init() const
+ {
+ if (m_is_initialized)
+ return;
+
+ m_endpoints.reserve(boost::size(m_mls) * 2);
+
+ m_has_interior = false;
typedef typename boost::range_iterator<MultiLinestring const>::type ls_iterator;
- for ( ls_iterator it = boost::begin(mls) ; it != boost::end(mls) ; ++it )
+ for ( ls_iterator it = boost::begin(m_mls) ; it != boost::end(m_mls) ; ++it )
{
typename boost::range_reference<MultiLinestring const>::type
ls = *it;
@@ -115,7 +177,7 @@ struct topology_check<MultiLinestring, multi_linestring_tag>
if (count > 0)
{
- has_interior = true;
+ m_has_interior = true;
}
if (count > 1)
@@ -138,62 +200,59 @@ struct topology_check<MultiLinestring, multi_linestring_tag>
// is not used anywhere in the code, still it's safer this way
if (! geometry::has_nan_coordinate(front_pt))
{
- endpoints.push_back(front_pt);
+ m_endpoints.push_back(front_pt);
}
if (! geometry::has_nan_coordinate(back_pt))
{
- endpoints.push_back(back_pt);
+ m_endpoints.push_back(back_pt);
}
}
}
}
- has_boundary = false;
+ m_has_boundary = false;
- if ( !endpoints.empty() )
+ if (! m_endpoints.empty() )
{
- std::sort(endpoints.begin(), endpoints.end(), geometry::less<point_type>());
- has_boundary = odd_counter(endpoints.begin(), endpoints.end());
+ std::sort(m_endpoints.begin(), m_endpoints.end(), relate::less());
+ m_has_boundary = find_odd_count(m_endpoints.begin(), m_endpoints.end());
}
+
+ m_is_initialized = true;
}
- struct not_ignoring_counter
+ template <typename It, typename Point>
+ static inline std::size_t count_equal(It first, It last, Point const& point)
{
- template <typename It>
- bool operator()(It first, It last) const
- {
- return find_odd_count(first, last);
- }
- };
+ std::pair<It, It> rng = std::equal_range(first, last, point, relate::less());
+ return (std::size_t)std::distance(rng.first, rng.second);
+ }
- template <typename Point>
- struct ignoring_counter
+ template <typename It>
+ static inline bool find_odd_count(It first, It last)
{
- ignoring_counter(Point const& pt) : m_pt(pt) {}
+ interrupting_visitor visitor;
+ for_each_boundary_point(first, last, visitor);
+ return visitor.found;
+ }
- template <typename It>
- bool operator()(It first, It last) const
+ struct interrupting_visitor
+ {
+ bool found;
+ interrupting_visitor() : found(false) {}
+ template <typename Point>
+ bool apply(Point const&)
{
- typedef typename std::iterator_traits<It>::value_type point_type;
-
- std::pair<It, It> ignore_range
- = std::equal_range(first, last, m_pt,
- geometry::less<point_type>());
-
- if ( find_odd_count(first, ignore_range.first) )
- return true;
-
- return find_odd_count(ignore_range.second, last);
+ found = true;
+ return false;
}
-
- Point const& m_pt;
};
- template <typename It>
- static inline bool find_odd_count(It first, It last)
+ template <typename It, typename Visitor>
+ static void for_each_boundary_point(It first, It last, Visitor& visitor)
{
if ( first == last )
- return false;
+ return;
std::size_t count = 1;
It prev = first;
@@ -203,8 +262,14 @@ struct topology_check<MultiLinestring, multi_linestring_tag>
// the end of the equal points subrange
if ( ! equals::equals_point_point(*first, *prev) )
{
+ // odd count -> boundary
if ( count % 2 != 0 )
- return true;
+ {
+ if (! visitor.apply(*prev))
+ {
+ return;
+ }
+ }
count = 1;
}
@@ -214,8 +279,22 @@ struct topology_check<MultiLinestring, multi_linestring_tag>
}
}
- return count % 2 != 0;
+ // odd count -> boundary
+ if ( count % 2 != 0 )
+ {
+ visitor.apply(*prev);
+ }
}
+
+private:
+ MultiLinestring const& m_mls;
+ mutable bool m_is_initialized;
+
+ mutable bool m_has_interior;
+ mutable bool m_has_boundary;
+
+ typedef typename geometry::point_type<MultiLinestring>::type point_type;
+ mutable std::vector<point_type> m_endpoints;
};
template <typename Ring>
@@ -223,12 +302,11 @@ struct topology_check<Ring, ring_tag>
{
static const char interior = '2';
static const char boundary = '1';
- static const bool has_interior = true;
- static const bool has_boundary = true;
topology_check(Ring const&) {}
- template <typename P>
- topology_check(Ring const&, P const&) {}
+
+ static bool has_interior() { return true; }
+ static bool has_boundary() { return true; }
};
template <typename Polygon>
@@ -236,12 +314,11 @@ struct topology_check<Polygon, polygon_tag>
{
static const char interior = '2';
static const char boundary = '1';
- static const bool has_interior = true;
- static const bool has_boundary = true;
-
+
topology_check(Polygon const&) {}
- template <typename P>
- topology_check(Polygon const&, P const&) {}
+
+ static bool has_interior() { return true; }
+ static bool has_boundary() { return true; }
};
template <typename MultiPolygon>
@@ -249,12 +326,13 @@ struct topology_check<MultiPolygon, multi_polygon_tag>
{
static const char interior = '2';
static const char boundary = '1';
- static const bool has_interior = true;
- static const bool has_boundary = true;
-
+
topology_check(MultiPolygon const&) {}
- template <typename P>
- topology_check(MultiPolygon const&, P const&) {}
+
+ static bool has_interior() { return true; }
+ static bool has_boundary() { return true; }
+ template <typename Point>
+ static bool check_boundary_point(Point const& ) { return true; }
};
}} // namespace detail::relate
diff --git a/boost/geometry/algorithms/detail/sections/section_functions.hpp b/boost/geometry/algorithms/detail/sections/section_functions.hpp
index 7bc5c08046..67df3060c4 100644
--- a/boost/geometry/algorithms/detail/sections/section_functions.hpp
+++ b/boost/geometry/algorithms/detail/sections/section_functions.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2017.
+// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -30,18 +30,87 @@ namespace detail { namespace section
template
<
std::size_t Dimension,
+ typename Geometry,
+ typename CastedCSTag = typename tag_cast
+ <
+ typename cs_tag<Geometry>::type,
+ spherical_tag
+ >::type
+>
+struct preceding_check
+{
+ template <typename Point, typename Box>
+ static inline bool apply(int dir, Point const& point, Box const& /*point_box*/, Box const& other_box)
+ {
+ return (dir == 1 && get<Dimension>(point) < get<min_corner, Dimension>(other_box))
+ || (dir == -1 && get<Dimension>(point) > get<max_corner, Dimension>(other_box));
+ }
+};
+
+template <typename Geometry>
+struct preceding_check<0, Geometry, spherical_tag>
+{
+ template <typename Point, typename Box>
+ static inline bool apply(int dir, Point const& point, Box const& point_box, Box const& other_box)
+ {
+ typedef typename select_coordinate_type
+ <
+ Point, Box
+ >::type calc_t;
+ typedef typename coordinate_system<Point>::type::units units_t;
+
+ calc_t const c0 = 0;
+
+ if (dir == 1)
+ {
+ calc_t const diff_min = math::longitude_distance_signed
+ <
+ units_t, calc_t
+ >(get<min_corner, 0>(other_box), get<0>(point));
+
+ calc_t const diff_min_min = math::longitude_distance_signed
+ <
+ units_t, calc_t
+ >(get<min_corner, 0>(other_box), get<min_corner, 0>(point_box));
+
+ return diff_min < c0 && diff_min_min <= c0 && diff_min_min <= diff_min;
+ }
+ else if (dir == -1)
+ {
+ calc_t const diff_max = math::longitude_distance_signed
+ <
+ units_t, calc_t
+ >(get<max_corner, 0>(other_box), get<0>(point));
+
+ calc_t const diff_max_max = math::longitude_distance_signed
+ <
+ units_t, calc_t
+ >(get<max_corner, 0>(other_box), get<max_corner, 0>(point_box));
+
+ return diff_max > c0 && diff_max_max >= c0 && diff_max <= diff_max_max;
+ }
+
+ return false;
+ }
+};
+
+
+template
+<
+ std::size_t Dimension,
typename Point,
typename RobustBox,
typename RobustPolicy
>
-static inline bool preceding(int dir, Point const& point,
- RobustBox const& robust_box,
- RobustPolicy const& robust_policy)
+static inline bool preceding(int dir,
+ Point const& point,
+ RobustBox const& point_robust_box,
+ RobustBox const& other_robust_box,
+ RobustPolicy const& robust_policy)
{
typename geometry::robust_point_type<Point, RobustPolicy>::type robust_point;
geometry::recalculate(robust_point, point, robust_policy);
- return (dir == 1 && get<Dimension>(robust_point) < get<min_corner, Dimension>(robust_box))
- || (dir == -1 && get<Dimension>(robust_point) > get<max_corner, Dimension>(robust_box));
+ return preceding_check<Dimension, Point>::apply(dir, robust_point, point_robust_box, other_robust_box);
}
template
@@ -51,14 +120,13 @@ template
typename RobustBox,
typename RobustPolicy
>
-static inline bool exceeding(int dir, Point const& point,
- RobustBox const& robust_box,
- RobustPolicy const& robust_policy)
+static inline bool exceeding(int dir,
+ Point const& point,
+ RobustBox const& point_robust_box,
+ RobustBox const& other_robust_box,
+ RobustPolicy const& robust_policy)
{
- typename geometry::robust_point_type<Point, RobustPolicy>::type robust_point;
- geometry::recalculate(robust_point, point, robust_policy);
- return (dir == 1 && get<Dimension>(robust_point) > get<max_corner, Dimension>(robust_box))
- || (dir == -1 && get<Dimension>(robust_point) < get<min_corner, Dimension>(robust_box));
+ return preceding<Dimension>(-dir, point, point_robust_box, other_robust_box, robust_policy);
}
diff --git a/boost/geometry/algorithms/detail/sections/sectionalize.hpp b/boost/geometry/algorithms/detail/sections/sectionalize.hpp
index 3ed5b8db07..f1d8e7d231 100644
--- a/boost/geometry/algorithms/detail/sections/sectionalize.hpp
+++ b/boost/geometry/algorithms/detail/sections/sectionalize.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013, 2014, 2015.
-// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017.
+// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -29,6 +29,8 @@
#include <boost/mpl/vector_c.hpp>
#include <boost/range.hpp>
#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_fundamental.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
@@ -54,6 +56,7 @@
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
+#include <boost/geometry/strategies/envelope.hpp>
namespace boost { namespace geometry
{
@@ -133,11 +136,21 @@ struct sections : std::vector<section<Box, DimensionCount> >
namespace detail { namespace sectionalize
{
+// NOTE: This utility will NOT work for latitudes, dimension 1 in spherical
+// and geographic coordinate system because in these coordinate systems
+// e.g. a segment on northern hemisphere may go towards greater latitude
+// and then towards lesser latitude.
template
<
+ typename Point,
typename DimensionVector,
std::size_t Index,
- std::size_t Count
+ std::size_t Count,
+ typename CastedCSTag = typename tag_cast
+ <
+ typename cs_tag<Point>::type,
+ spherical_tag
+ >::type
>
struct get_direction_loop
{
@@ -158,21 +171,67 @@ struct get_direction_loop
get_direction_loop
<
+ Point,
DimensionVector,
Index + 1,
- Count
+ Count,
+ CastedCSTag
+ >::apply(seg, directions);
+ }
+};
+
+template
+<
+ typename Point,
+ typename DimensionVector,
+ std::size_t Count
+>
+struct get_direction_loop<Point, DimensionVector, 0, Count, spherical_tag>
+{
+ typedef typename boost::mpl::at_c<DimensionVector, 0>::type dimension;
+
+ template <typename Segment>
+ static inline void apply(Segment const& seg,
+ int directions[Count])
+ {
+ typedef typename coordinate_type<Segment>::type coordinate_type;
+ typedef typename coordinate_system<Point>::type::units units_t;
+
+ coordinate_type const diff = math::longitude_distance_signed
+ <
+ units_t, coordinate_type
+ >(geometry::get<0, 0>(seg),
+ geometry::get<1, 0>(seg));
+
+ coordinate_type zero = coordinate_type();
+ directions[0] = diff > zero ? 1 : diff < zero ? -1 : 0;
+
+ get_direction_loop
+ <
+ Point,
+ DimensionVector,
+ 1,
+ Count,
+ spherical_tag
>::apply(seg, directions);
}
};
-template <typename DimensionVector, std::size_t Count>
-struct get_direction_loop<DimensionVector, Count, Count>
+template
+<
+ typename Point,
+ typename DimensionVector,
+ std::size_t Count,
+ typename CastedCSTag
+>
+struct get_direction_loop<Point, DimensionVector, Count, Count, CastedCSTag>
{
template <typename Segment>
static inline void apply(Segment const&, int [Count])
{}
};
+
//! Copy one static array to another
template <typename T, std::size_t Index, std::size_t Count>
struct copy_loop
@@ -272,19 +331,21 @@ struct assign_loop<T, Count, Count>
template <typename CSTag>
struct box_first_in_section
{
- template <typename Box, typename Point>
- static inline void apply(Box & box, Point const& prev, Point const& curr)
+ template <typename Box, typename Point, typename Strategy>
+ static inline void apply(Box & box, Point const& prev, Point const& curr,
+ Strategy const& strategy)
{
geometry::model::referring_segment<Point const> seg(prev, curr);
- geometry::envelope(seg, box);
+ geometry::envelope(seg, box, strategy);
}
};
template <>
struct box_first_in_section<cartesian_tag>
{
- template <typename Box, typename Point>
- static inline void apply(Box & box, Point const& prev, Point const& curr)
+ template <typename Box, typename Point, typename Strategy>
+ static inline void apply(Box & box, Point const& prev, Point const& curr,
+ Strategy const& )
{
geometry::envelope(prev, box);
geometry::expand(box, curr);
@@ -294,19 +355,21 @@ struct box_first_in_section<cartesian_tag>
template <typename CSTag>
struct box_next_in_section
{
- template <typename Box, typename Point>
- static inline void apply(Box & box, Point const& prev, Point const& curr)
+ template <typename Box, typename Point, typename Strategy>
+ static inline void apply(Box & box, Point const& prev, Point const& curr,
+ Strategy const& strategy)
{
geometry::model::referring_segment<Point const> seg(prev, curr);
- geometry::expand(box, seg);
+ geometry::expand(box, seg, strategy);
}
};
template <>
struct box_next_in_section<cartesian_tag>
{
- template <typename Box, typename Point>
- static inline void apply(Box & box, Point const& , Point const& curr)
+ template <typename Box, typename Point, typename Strategy>
+ static inline void apply(Box & box, Point const& , Point const& curr,
+ Strategy const& )
{
geometry::expand(box, curr);
}
@@ -335,6 +398,30 @@ struct sectionalize_part
ring_identifier ring_id,
std::size_t max_count)
{
+ typedef typename strategy::envelope::services::default_strategy
+ <
+ typename cs_tag<typename Sections::box_type>::type
+ >::type envelope_strategy_type;
+
+ apply(sections, begin, end,
+ robust_policy, envelope_strategy_type(),
+ ring_id, max_count);
+ }
+
+ template
+ <
+ typename Iterator,
+ typename RobustPolicy,
+ typename Sections,
+ typename EnvelopeStrategy
+ >
+ static inline void apply(Sections& sections,
+ Iterator begin, Iterator end,
+ RobustPolicy const& robust_policy,
+ EnvelopeStrategy const& strategy,
+ ring_identifier ring_id,
+ std::size_t max_count)
+ {
boost::ignore_unused_variable_warning(robust_policy);
typedef typename boost::range_value<Sections>::type section_type;
@@ -379,7 +466,7 @@ struct sectionalize_part
int direction_classes[dimension_count] = {0};
get_direction_loop
<
- DimensionVector, 0, dimension_count
+ Point, DimensionVector, 0, dimension_count
>::apply(robust_segment, direction_classes);
// if "dir" == 0 for all point-dimensions, it is duplicate.
@@ -449,14 +536,14 @@ struct sectionalize_part
// In cartesian this is envelope of previous point expanded with current point
// in non-cartesian this is envelope of a segment
box_first_in_section<typename cs_tag<robust_point_type>::type>
- ::apply(section.bounding_box, previous_robust_point, current_robust_point);
+ ::apply(section.bounding_box, previous_robust_point, current_robust_point, strategy);
}
else
{
// In cartesian this is expand with current point
// in non-cartesian this is expand with a segment
box_next_in_section<typename cs_tag<robust_point_type>::type>
- ::apply(section.bounding_box, previous_robust_point, current_robust_point);
+ ::apply(section.bounding_box, previous_robust_point, current_robust_point, strategy);
}
section.end_index = index + 1;
@@ -501,11 +588,13 @@ struct sectionalize_range
<
typename Range,
typename RobustPolicy,
- typename Sections
+ typename Sections,
+ typename EnvelopeStrategy
>
static inline void apply(Range const& range,
RobustPolicy const& robust_policy,
Sections& sections,
+ EnvelopeStrategy const& strategy,
ring_identifier ring_id,
std::size_t max_count)
{
@@ -534,7 +623,7 @@ struct sectionalize_range
sectionalize_part<Point, DimensionVector>::apply(sections,
boost::begin(view), boost::end(view),
- robust_policy, ring_id, max_count);
+ robust_policy, strategy, ring_id, max_count);
}
};
@@ -549,12 +638,15 @@ struct sectionalize_polygon
<
typename Polygon,
typename RobustPolicy,
- typename Sections
+ typename Sections,
+ typename EnvelopeStrategy
>
static inline void apply(Polygon const& poly,
RobustPolicy const& robust_policy,
Sections& sections,
- ring_identifier ring_id, std::size_t max_count)
+ EnvelopeStrategy const& strategy,
+ ring_identifier ring_id,
+ std::size_t max_count)
{
typedef typename point_type<Polygon>::type point_type;
typedef sectionalize_range
@@ -564,7 +656,7 @@ struct sectionalize_polygon
> per_range;
ring_id.ring_index = -1;
- per_range::apply(exterior_ring(poly), robust_policy, sections, ring_id, max_count);
+ per_range::apply(exterior_ring(poly), robust_policy, sections, strategy, ring_id, max_count);
ring_id.ring_index++;
typename interior_return_type<Polygon const>::type
@@ -572,7 +664,7 @@ struct sectionalize_polygon
for (typename detail::interior_iterator<Polygon const>::type
it = boost::begin(rings); it != boost::end(rings); ++it, ++ring_id.ring_index)
{
- per_range::apply(*it, robust_policy, sections, ring_id, max_count);
+ per_range::apply(*it, robust_policy, sections, strategy, ring_id, max_count);
}
}
};
@@ -584,11 +676,13 @@ struct sectionalize_box
<
typename Box,
typename RobustPolicy,
- typename Sections
+ typename Sections,
+ typename EnvelopeStrategy
>
static inline void apply(Box const& box,
RobustPolicy const& robust_policy,
Sections& sections,
+ EnvelopeStrategy const& ,
ring_identifier const& ring_id, std::size_t max_count)
{
typedef typename point_type<Box>::type point_type;
@@ -613,12 +707,15 @@ struct sectionalize_box
points.push_back(lr);
points.push_back(ll);
+ // NOTE: Use cartesian envelope strategy in all coordinate systems
+ // because edges of a box are not geodesic segments
sectionalize_range
<
closed, false,
point_type,
DimensionVector
>::apply(points, robust_policy, sections,
+ strategy::envelope::cartesian_segment<>(),
ring_id, max_count);
}
};
@@ -630,11 +727,15 @@ struct sectionalize_multi
<
typename MultiGeometry,
typename RobustPolicy,
- typename Sections
+ typename Sections,
+ typename EnvelopeStrategy
>
static inline void apply(MultiGeometry const& multi,
RobustPolicy const& robust_policy,
- Sections& sections, ring_identifier ring_id, std::size_t max_count)
+ Sections& sections,
+ EnvelopeStrategy const& strategy,
+ ring_identifier ring_id,
+ std::size_t max_count)
{
ring_id.multi_index = 0;
for (typename boost::range_iterator<MultiGeometry const>::type
@@ -642,7 +743,7 @@ struct sectionalize_multi
it != boost::end(multi);
++it, ++ring_id.multi_index)
{
- Policy::apply(*it, robust_policy, sections, ring_id, max_count);
+ Policy::apply(*it, robust_policy, sections, strategy, ring_id, max_count);
}
}
};
@@ -814,14 +915,18 @@ template
typename DimensionVector,
typename Geometry,
typename Sections,
- typename RobustPolicy
+ typename RobustPolicy,
+ typename EnvelopeStrategy
>
inline void sectionalize(Geometry const& geometry,
RobustPolicy const& robust_policy,
Sections& sections,
+ EnvelopeStrategy const& strategy,
int source_index = 0,
std::size_t max_count = 10)
{
+ BOOST_STATIC_ASSERT((! boost::is_fundamental<EnvelopeStrategy>::value));
+
concepts::check<Geometry const>();
typedef typename boost::range_value<Sections>::type section_type;
@@ -855,12 +960,39 @@ inline void sectionalize(Geometry const& geometry,
Geometry,
Reverse,
DimensionVector
- >::apply(geometry, robust_policy, sections, ring_id, max_count);
+ >::apply(geometry, robust_policy, sections, strategy, ring_id, max_count);
detail::sectionalize::enlarge_sections(sections);
}
+template
+<
+ bool Reverse,
+ typename DimensionVector,
+ typename Geometry,
+ typename Sections,
+ typename RobustPolicy
+>
+inline void sectionalize(Geometry const& geometry,
+ RobustPolicy const& robust_policy,
+ Sections& sections,
+ int source_index = 0,
+ std::size_t max_count = 10)
+{
+ typedef typename strategy::envelope::services::default_strategy
+ <
+ typename cs_tag<Geometry>::type
+ >::type envelope_strategy_type;
+
+ boost::geometry::sectionalize
+ <
+ Reverse, DimensionVector
+ >(geometry, robust_policy, sections,
+ envelope_strategy_type(),
+ source_index, max_count);
+}
+
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/touches/implementation.hpp b/boost/geometry/algorithms/detail/touches/implementation.hpp
new file mode 100644
index 0000000000..94f1fba581
--- /dev/null
+++ b/boost/geometry/algorithms/detail/touches/implementation.hpp
@@ -0,0 +1,459 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
+// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
+
+// This file was modified by Oracle on 2013, 2014, 2015, 2017.
+// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the 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_GEOMETRY_ALGORITHMS_DETAIL_TOUCHES_IMPLEMENTATION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_TOUCHES_IMPLEMENTATION_HPP
+
+
+#include <boost/geometry/algorithms/detail/for_each_range.hpp>
+#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
+#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
+#include <boost/geometry/algorithms/detail/sub_range.hpp>
+#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
+#include <boost/geometry/algorithms/detail/touches/interface.hpp>
+#include <boost/geometry/algorithms/disjoint.hpp>
+#include <boost/geometry/algorithms/intersects.hpp>
+#include <boost/geometry/algorithms/num_geometries.hpp>
+#include <boost/geometry/algorithms/relate.hpp>
+
+#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace touches
+{
+
+// Box/Box
+
+template
+<
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct box_box_loop
+{
+ template <typename Box1, typename Box2>
+ static inline bool apply(Box1 const& b1, Box2 const& b2, bool & touch)
+ {
+ typedef typename coordinate_type<Box1>::type coordinate_type1;
+ typedef typename coordinate_type<Box2>::type coordinate_type2;
+
+ coordinate_type1 const& min1 = get<min_corner, Dimension>(b1);
+ coordinate_type1 const& max1 = get<max_corner, Dimension>(b1);
+ coordinate_type2 const& min2 = get<min_corner, Dimension>(b2);
+ coordinate_type2 const& max2 = get<max_corner, Dimension>(b2);
+
+ // TODO assert or exception?
+ //BOOST_GEOMETRY_ASSERT(min1 <= max1 && min2 <= max2);
+
+ if (max1 < min2 || max2 < min1)
+ {
+ return false;
+ }
+
+ if (max1 == min2 || max2 == min1)
+ {
+ touch = true;
+ }
+
+ return box_box_loop
+ <
+ Dimension + 1,
+ DimensionCount
+ >::apply(b1, b2, touch);
+ }
+};
+
+template
+<
+ std::size_t DimensionCount
+>
+struct box_box_loop<DimensionCount, DimensionCount>
+{
+ template <typename Box1, typename Box2>
+ static inline bool apply(Box1 const& , Box2 const&, bool &)
+ {
+ return true;
+ }
+};
+
+struct box_box
+{
+ template <typename Box1, typename Box2, typename Strategy>
+ static inline bool apply(Box1 const& b1, Box2 const& b2, Strategy const& /*strategy*/)
+ {
+ BOOST_STATIC_ASSERT((boost::is_same
+ <
+ typename geometry::coordinate_system<Box1>::type,
+ typename geometry::coordinate_system<Box2>::type
+ >::value
+ ));
+ assert_dimension_equal<Box1, Box2>();
+
+ bool touches = false;
+ bool ok = box_box_loop
+ <
+ 0,
+ dimension<Box1>::type::value
+ >::apply(b1, b2, touches);
+
+ return ok && touches;
+ }
+};
+
+// Areal/Areal
+
+struct areal_interrupt_policy
+{
+ static bool const enabled = true;
+ bool found_touch;
+ bool found_not_touch;
+
+ // dummy variable required by self_get_turn_points::get_turns
+ static bool const has_intersections = false;
+
+ inline bool result()
+ {
+ return found_touch && !found_not_touch;
+ }
+
+ inline areal_interrupt_policy()
+ : found_touch(false), found_not_touch(false)
+ {}
+
+ template <typename Range>
+ inline bool apply(Range const& range)
+ {
+ // if already rejected (temp workaround?)
+ if ( found_not_touch )
+ return true;
+
+ typedef typename boost::range_iterator<Range const>::type iterator;
+ for ( iterator it = boost::begin(range) ; it != boost::end(range) ; ++it )
+ {
+ if ( it->has(overlay::operation_intersection) )
+ {
+ found_not_touch = true;
+ return true;
+ }
+
+ switch(it->method)
+ {
+ case overlay::method_crosses:
+ found_not_touch = true;
+ return true;
+ case overlay::method_equal:
+ // Segment spatially equal means: at the right side
+ // the polygon internally overlaps. So return false.
+ found_not_touch = true;
+ return true;
+ case overlay::method_touch:
+ case overlay::method_touch_interior:
+ case overlay::method_collinear:
+ if ( ok_for_touch(*it) )
+ {
+ found_touch = true;
+ }
+ else
+ {
+ found_not_touch = true;
+ return true;
+ }
+ break;
+ case overlay::method_none :
+ case overlay::method_disjoint :
+ case overlay::method_error :
+ break;
+ }
+ }
+
+ return false;
+ }
+
+ template <typename Turn>
+ inline bool ok_for_touch(Turn const& turn)
+ {
+ return turn.both(overlay::operation_union)
+ || turn.both(overlay::operation_blocked)
+ || turn.combination(overlay::operation_union, overlay::operation_blocked)
+ ;
+ }
+};
+
+template<typename Geometry, typename PointInRingStrategy>
+struct check_each_ring_for_within
+{
+ bool has_within;
+ Geometry const& m_geometry;
+ PointInRingStrategy const& m_strategy;
+
+ inline check_each_ring_for_within(Geometry const& g, PointInRingStrategy const& strategy)
+ : has_within(false)
+ , m_geometry(g)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Range>
+ inline void apply(Range const& range)
+ {
+ typename geometry::point_type<Range>::type p;
+ geometry::point_on_border(p, range);
+ if ( !has_within && geometry::within(p, m_geometry, m_strategy) )
+ {
+ has_within = true;
+ }
+ }
+};
+
+template <typename FirstGeometry, typename SecondGeometry, typename IntersectionStrategy>
+inline bool rings_containing(FirstGeometry const& geometry1,
+ SecondGeometry const& geometry2,
+ IntersectionStrategy const& strategy)
+{
+ // NOTE: This strategy could be defined inside IntersectionStrategy
+ typedef typename IntersectionStrategy::template point_in_geometry_strategy
+ <
+ FirstGeometry, SecondGeometry
+ >::type point_in_ring_strategy_type;
+
+ point_in_ring_strategy_type point_in_ring_strategy
+ = strategy.template get_point_in_geometry_strategy<FirstGeometry, SecondGeometry>();
+
+ check_each_ring_for_within
+ <
+ FirstGeometry, point_in_ring_strategy_type
+ > checker(geometry1, point_in_ring_strategy);
+ geometry::detail::for_each_range(geometry2, checker);
+ return checker.has_within;
+}
+
+template <typename Geometry1, typename Geometry2>
+struct areal_areal
+{
+ template <typename IntersectionStrategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ IntersectionStrategy const& strategy)
+ {
+ typedef detail::no_rescale_policy rescale_policy_type;
+ typedef typename geometry::point_type<Geometry1>::type point_type;
+ typedef detail::overlay::turn_info
+ <
+ point_type,
+ typename segment_ratio_type<point_type, rescale_policy_type>::type
+ > turn_info;
+
+ std::deque<turn_info> turns;
+ detail::touches::areal_interrupt_policy policy;
+ rescale_policy_type robust_policy;
+ boost::geometry::get_turns
+ <
+ detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
+ detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
+ detail::overlay::assign_null_policy
+ >(geometry1, geometry2, strategy, robust_policy, turns, policy);
+
+ return policy.result()
+ && ! geometry::detail::touches::rings_containing(geometry1, geometry2, strategy)
+ && ! geometry::detail::touches::rings_containing(geometry2, geometry1, strategy);
+ }
+};
+
+// P/*
+
+struct use_point_in_geometry
+{
+ template <typename Point, typename Geometry, typename Strategy>
+ static inline bool apply(Point const& point, Geometry const& geometry, Strategy const& strategy)
+ {
+ return detail::within::point_in_geometry(point, geometry, strategy) == 0;
+ }
+};
+
+
+}}
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+// P/P
+
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct touches<Geometry1, Geometry2, point_tag, Tag2, pointlike_tag, pointlike_tag, false>
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& , Geometry2 const& , Strategy const&)
+ {
+ return false;
+ }
+};
+
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct touches<Geometry1, Geometry2, multi_point_tag, Tag2, pointlike_tag, pointlike_tag, false>
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const&, Geometry2 const&, Strategy const&)
+ {
+ return false;
+ }
+};
+
+// P/*
+
+template <typename Point, typename Geometry, typename Tag2, typename CastedTag2>
+struct touches<Point, Geometry, point_tag, Tag2, pointlike_tag, CastedTag2, false>
+ : detail::touches::use_point_in_geometry
+{};
+
+template <typename MultiPoint, typename MultiGeometry, typename Tag2, typename CastedTag2>
+struct touches<MultiPoint, MultiGeometry, multi_point_tag, Tag2, pointlike_tag, CastedTag2, false>
+ : detail::relate::relate_impl
+ <
+ detail::de9im::static_mask_touches_type,
+ MultiPoint,
+ MultiGeometry
+ >
+{};
+
+template <typename Geometry, typename MultiPoint, typename Tag1, typename CastedTag1>
+struct touches<Geometry, MultiPoint, Tag1, multi_point_tag, CastedTag1, pointlike_tag, false>
+ : detail::relate::relate_impl
+ <
+ detail::de9im::static_mask_touches_type,
+ Geometry,
+ MultiPoint
+ >
+{};
+
+// Box/Box
+
+template <typename Box1, typename Box2, typename CastedTag1, typename CastedTag2>
+struct touches<Box1, Box2, box_tag, box_tag, CastedTag1, CastedTag2, false>
+ : detail::touches::box_box
+{};
+
+template <typename Box1, typename Box2>
+struct touches<Box1, Box2, box_tag, box_tag, areal_tag, areal_tag, false>
+ : detail::touches::box_box
+{};
+
+// L/L
+
+template <typename Linear1, typename Linear2, typename Tag1, typename Tag2>
+struct touches<Linear1, Linear2, Tag1, Tag2, linear_tag, linear_tag, false>
+ : detail::relate::relate_impl
+ <
+ detail::de9im::static_mask_touches_type,
+ Linear1,
+ Linear2
+ >
+{};
+
+// L/A
+
+template <typename Linear, typename Areal, typename Tag1, typename Tag2>
+struct touches<Linear, Areal, Tag1, Tag2, linear_tag, areal_tag, false>
+ : detail::relate::relate_impl
+ <
+ detail::de9im::static_mask_touches_type,
+ Linear,
+ Areal
+ >
+{};
+
+// A/L
+template <typename Linear, typename Areal, typename Tag1, typename Tag2>
+struct touches<Areal, Linear, Tag1, Tag2, areal_tag, linear_tag, false>
+ : detail::relate::relate_impl
+ <
+ detail::de9im::static_mask_touches_type,
+ Areal,
+ Linear
+ >
+{};
+
+// A/A
+
+template <typename Areal1, typename Areal2, typename Tag1, typename Tag2>
+struct touches<Areal1, Areal2, Tag1, Tag2, areal_tag, areal_tag, false>
+ : detail::relate::relate_impl
+ <
+ detail::de9im::static_mask_touches_type,
+ Areal1,
+ Areal2
+ >
+{};
+
+template <typename Areal1, typename Areal2>
+struct touches<Areal1, Areal2, ring_tag, ring_tag, areal_tag, areal_tag, false>
+ : detail::touches::areal_areal<Areal1, Areal2>
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+namespace resolve_variant {
+
+template <typename Geometry>
+struct self_touches
+{
+ static bool apply(Geometry const& geometry)
+ {
+ concepts::check<Geometry const>();
+
+ typedef typename strategy::relate::services::default_strategy
+ <
+ Geometry, Geometry
+ >::type strategy_type;
+ typedef detail::no_rescale_policy rescale_policy_type;
+ typedef typename geometry::point_type<Geometry>::type point_type;
+ typedef detail::overlay::turn_info
+ <
+ point_type,
+ typename segment_ratio_type<point_type, rescale_policy_type>::type
+ > turn_info;
+
+ typedef detail::overlay::get_turn_info
+ <
+ detail::overlay::assign_null_policy
+ > policy_type;
+
+ std::deque<turn_info> turns;
+ detail::touches::areal_interrupt_policy policy;
+ strategy_type strategy;
+ rescale_policy_type robust_policy;
+ detail::self_get_turn_points::get_turns
+ <
+ false, policy_type
+ >::apply(geometry, strategy, robust_policy, turns, policy, 0);
+
+ return policy.result();
+ }
+};
+
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_TOUCHES_IMPLEMENTATION_HPP
diff --git a/boost/geometry/algorithms/detail/touches/interface.hpp b/boost/geometry/algorithms/detail/touches/interface.hpp
new file mode 100644
index 0000000000..d2e0cc8c4e
--- /dev/null
+++ b/boost/geometry/algorithms/detail/touches/interface.hpp
@@ -0,0 +1,321 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
+// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
+
+// This file was modified by Oracle on 2013, 2014, 2015, 2017.
+// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the 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_GEOMETRY_ALGORITHMS_DETAIL_TOUCHES_INTERFACE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_TOUCHES_INTERFACE_HPP
+
+
+#include <deque>
+
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
+
+#include <boost/geometry/core/reverse_dispatch.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tag_cast.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/strategies/relate.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+// TODO: Since CastedTags are used is Reverse needed?
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Tag1 = typename tag<Geometry1>::type,
+ typename Tag2 = typename tag<Geometry2>::type,
+ typename CastedTag1 = typename tag_cast<Tag1, pointlike_tag, linear_tag, areal_tag>::type,
+ typename CastedTag2 = typename tag_cast<Tag2, pointlike_tag, linear_tag, areal_tag>::type,
+ bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
+>
+struct touches
+ : not_implemented<Tag1, Tag2>
+{};
+
+// If reversal is needed, perform it
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1, typename Tag2,
+ typename CastedTag1, typename CastedTag2
+>
+struct touches<Geometry1, Geometry2, Tag1, Tag2, CastedTag1, CastedTag2, true>
+ : touches<Geometry2, Geometry1, Tag2, Tag1, CastedTag2, CastedTag1, false>
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
+ {
+ return touches<Geometry2, Geometry1>::apply(g2, g1, strategy);
+ }
+};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+namespace resolve_strategy
+{
+
+struct touches
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ return dispatch::touches
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy);
+ }
+
+ template <typename Geometry1, typename Geometry2>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ default_strategy)
+ {
+ typedef typename strategy::relate::services::default_strategy
+ <
+ Geometry1,
+ Geometry2
+ >::type strategy_type;
+
+ return dispatch::touches
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy_type());
+ }
+};
+
+} // namespace resolve_strategy
+
+
+namespace resolve_variant {
+
+template <typename Geometry1, typename Geometry2>
+struct touches
+{
+ template <typename Strategy>
+ static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
+ {
+ concepts::check<Geometry1 const>();
+ concepts::check<Geometry2 const>();
+
+ return resolve_strategy::touches::apply(geometry1, geometry2, strategy);
+ }
+};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
+struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+{
+ template <typename Strategy>
+ struct visitor: boost::static_visitor<bool>
+ {
+ Geometry2 const& m_geometry2;
+ Strategy const& m_strategy;
+
+ visitor(Geometry2 const& geometry2, Strategy const& strategy)
+ : m_geometry2(geometry2)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry1>
+ bool operator()(Geometry1 const& geometry1) const
+ {
+ return touches<Geometry1, Geometry2>::apply(geometry1, m_geometry2, m_strategy);
+ }
+ };
+
+ template <typename Strategy>
+ static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
+ }
+};
+
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct touches<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ template <typename Strategy>
+ struct visitor: boost::static_visitor<bool>
+ {
+ Geometry1 const& m_geometry1;
+ Strategy const& m_strategy;
+
+ visitor(Geometry1 const& geometry1, Strategy const& strategy)
+ : m_geometry1(geometry1)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry2>
+ bool operator()(Geometry2 const& geometry2) const
+ {
+ return touches<Geometry1, Geometry2>::apply(m_geometry1, geometry2, m_strategy);
+ }
+ };
+
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
+ Strategy const& strategy)
+ {
+ return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
+ }
+};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T1),
+ BOOST_VARIANT_ENUM_PARAMS(typename T2)>
+struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
+{
+ template <typename Strategy>
+ struct visitor: boost::static_visitor<bool>
+ {
+ Strategy const& m_strategy;
+
+ visitor(Strategy const& strategy)
+ : m_strategy(strategy)
+ {}
+
+ template <typename Geometry1, typename Geometry2>
+ bool operator()(Geometry1 const& geometry1,
+ Geometry2 const& geometry2) const
+ {
+ return touches<Geometry1, Geometry2>::apply(geometry1, geometry2, m_strategy);
+ }
+ };
+
+ template <typename Strategy>
+ static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
+ Strategy const& strategy)
+ {
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
+ }
+};
+
+template <typename Geometry>
+struct self_touches;
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct self_touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ struct visitor: boost::static_visitor<bool>
+ {
+ template <typename Geometry>
+ bool operator()(Geometry const& geometry) const
+ {
+ return self_touches<Geometry>::apply(geometry);
+ }
+ };
+
+ static inline bool
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
+ {
+ return boost::apply_visitor(visitor(), geometry);
+ }
+};
+
+} // namespace resolve_variant
+
+
+/*!
+\brief \brief_check{has at least one touching point (self-tangency)}
+\note This function can be called for one geometry (self-tangency) and
+ also for two geometries (touch)
+\ingroup touches
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry
+\return \return_check{is self-touching}
+
+\qbk{distinguish,one geometry}
+\qbk{[def __one_parameter__]}
+\qbk{[include reference/algorithms/touches.qbk]}
+*/
+template <typename Geometry>
+inline bool touches(Geometry const& geometry)
+{
+ return resolve_variant::self_touches<Geometry>::apply(geometry);
+}
+
+
+/*!
+\brief \brief_check2{have at least one touching point (tangent - non overlapping)}
+\ingroup touches
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\return \return_check2{touch each other}
+
+\qbk{distinguish,two geometries}
+\qbk{[include reference/algorithms/touches.qbk]}
+ */
+template <typename Geometry1, typename Geometry2>
+inline bool touches(Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ return resolve_variant::touches
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, default_strategy());
+}
+
+/*!
+\brief \brief_check2{have at least one touching point (tangent - non overlapping)}
+\ingroup touches
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Strategy \tparam_strategy{Touches}
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param strategy \param_strategy{touches}
+\return \return_check2{touch each other}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/touches.qbk]}
+ */
+template <typename Geometry1, typename Geometry2, typename Strategy>
+inline bool touches(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ return resolve_variant::touches
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy);
+}
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_TOUCHES_INTERFACE_HPP
diff --git a/boost/geometry/algorithms/detail/within/implementation.hpp b/boost/geometry/algorithms/detail/within/implementation.hpp
new file mode 100644
index 0000000000..8f1eba62e6
--- /dev/null
+++ b/boost/geometry/algorithms/detail/within/implementation.hpp
@@ -0,0 +1,306 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// This file was modified by Oracle on 2013, 2014, 2017.
+// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the 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_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_IMPLEMENTATION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_IMPLEMENTATION_HPP
+
+
+#include <cstddef>
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/algorithms/detail/within/interface.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/point_order.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/order_as_direction.hpp>
+#include <boost/geometry/views/closeable_view.hpp>
+#include <boost/geometry/views/reversible_view.hpp>
+
+#include <boost/geometry/algorithms/detail/within/multi_point.hpp>
+#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
+#include <boost/geometry/algorithms/relate.hpp>
+
+#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
+#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
+#include <deque>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace within {
+
+struct use_point_in_geometry
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
+ {
+ return detail::within::point_in_geometry(geometry1, geometry2, strategy) == 1;
+ }
+};
+
+struct use_relate
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
+ {
+ typedef typename detail::de9im::static_mask_within_type
+ <
+ Geometry1, Geometry2
+ >::type within_mask;
+ return geometry::relate(geometry1, geometry2, within_mask(), strategy);
+ }
+};
+
+}} // namespace detail::within
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Point, typename Box>
+struct within<Point, Box, point_tag, box_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
+ {
+ boost::ignore_unused_variable_warning(strategy);
+ return strategy.apply(point, box);
+ }
+};
+
+template <typename Box1, typename Box2>
+struct within<Box1, Box2, box_tag, box_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
+ {
+ assert_dimension_equal<Box1, Box2>();
+ boost::ignore_unused_variable_warning(strategy);
+ return strategy.apply(box1, box2);
+ }
+};
+
+// P/P
+
+template <typename Point1, typename Point2>
+struct within<Point1, Point2, point_tag, point_tag>
+ : public detail::within::use_point_in_geometry
+{};
+
+template <typename Point, typename MultiPoint>
+struct within<Point, MultiPoint, point_tag, multi_point_tag>
+ : public detail::within::use_point_in_geometry
+{};
+
+template <typename MultiPoint, typename Point>
+struct within<MultiPoint, Point, multi_point_tag, point_tag>
+ : public detail::within::multi_point_point
+{};
+
+template <typename MultiPoint1, typename MultiPoint2>
+struct within<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag>
+ : public detail::within::multi_point_multi_point
+{};
+
+// P/L
+
+template <typename Point, typename Segment>
+struct within<Point, Segment, point_tag, segment_tag>
+ : public detail::within::use_point_in_geometry
+{};
+
+template <typename Point, typename Linestring>
+struct within<Point, Linestring, point_tag, linestring_tag>
+ : public detail::within::use_point_in_geometry
+{};
+
+template <typename Point, typename MultiLinestring>
+struct within<Point, MultiLinestring, point_tag, multi_linestring_tag>
+ : public detail::within::use_point_in_geometry
+{};
+
+template <typename MultiPoint, typename Segment>
+struct within<MultiPoint, Segment, multi_point_tag, segment_tag>
+ : public detail::within::multi_point_single_geometry<true>
+{};
+
+template <typename MultiPoint, typename Linestring>
+struct within<MultiPoint, Linestring, multi_point_tag, linestring_tag>
+ : public detail::within::multi_point_single_geometry<true>
+{};
+
+template <typename MultiPoint, typename MultiLinestring>
+struct within<MultiPoint, MultiLinestring, multi_point_tag, multi_linestring_tag>
+ : public detail::within::multi_point_multi_geometry<true>
+{};
+
+// P/A
+
+template <typename Point, typename Ring>
+struct within<Point, Ring, point_tag, ring_tag>
+ : public detail::within::use_point_in_geometry
+{};
+
+template <typename Point, typename Polygon>
+struct within<Point, Polygon, point_tag, polygon_tag>
+ : public detail::within::use_point_in_geometry
+{};
+
+template <typename Point, typename MultiPolygon>
+struct within<Point, MultiPolygon, point_tag, multi_polygon_tag>
+ : public detail::within::use_point_in_geometry
+{};
+
+template <typename MultiPoint, typename Ring>
+struct within<MultiPoint, Ring, multi_point_tag, ring_tag>
+ : public detail::within::multi_point_single_geometry<true>
+{};
+
+template <typename MultiPoint, typename Polygon>
+struct within<MultiPoint, Polygon, multi_point_tag, polygon_tag>
+ : public detail::within::multi_point_single_geometry<true>
+{};
+
+template <typename MultiPoint, typename MultiPolygon>
+struct within<MultiPoint, MultiPolygon, multi_point_tag, multi_polygon_tag>
+ : public detail::within::multi_point_multi_geometry<true>
+{};
+
+// L/L
+
+template <typename Linestring1, typename Linestring2>
+struct within<Linestring1, Linestring2, linestring_tag, linestring_tag>
+ : public detail::within::use_relate
+{};
+
+template <typename Linestring, typename MultiLinestring>
+struct within<Linestring, MultiLinestring, linestring_tag, multi_linestring_tag>
+ : public detail::within::use_relate
+{};
+
+template <typename MultiLinestring, typename Linestring>
+struct within<MultiLinestring, Linestring, multi_linestring_tag, linestring_tag>
+ : public detail::within::use_relate
+{};
+
+template <typename MultiLinestring1, typename MultiLinestring2>
+struct within<MultiLinestring1, MultiLinestring2, multi_linestring_tag, multi_linestring_tag>
+ : public detail::within::use_relate
+{};
+
+// L/A
+
+template <typename Linestring, typename Ring>
+struct within<Linestring, Ring, linestring_tag, ring_tag>
+ : public detail::within::use_relate
+{};
+
+template <typename MultiLinestring, typename Ring>
+struct within<MultiLinestring, Ring, multi_linestring_tag, ring_tag>
+ : public detail::within::use_relate
+{};
+
+template <typename Linestring, typename Polygon>
+struct within<Linestring, Polygon, linestring_tag, polygon_tag>
+ : public detail::within::use_relate
+{};
+
+template <typename MultiLinestring, typename Polygon>
+struct within<MultiLinestring, Polygon, multi_linestring_tag, polygon_tag>
+ : public detail::within::use_relate
+{};
+
+template <typename Linestring, typename MultiPolygon>
+struct within<Linestring, MultiPolygon, linestring_tag, multi_polygon_tag>
+ : public detail::within::use_relate
+{};
+
+template <typename MultiLinestring, typename MultiPolygon>
+struct within<MultiLinestring, MultiPolygon, multi_linestring_tag, multi_polygon_tag>
+ : public detail::within::use_relate
+{};
+
+// A/A
+
+template <typename Ring1, typename Ring2>
+struct within<Ring1, Ring2, ring_tag, ring_tag>
+ : public detail::within::use_relate
+{};
+
+template <typename Ring, typename Polygon>
+struct within<Ring, Polygon, ring_tag, polygon_tag>
+ : public detail::within::use_relate
+{};
+
+template <typename Polygon, typename Ring>
+struct within<Polygon, Ring, polygon_tag, ring_tag>
+ : public detail::within::use_relate
+{};
+
+template <typename Polygon1, typename Polygon2>
+struct within<Polygon1, Polygon2, polygon_tag, polygon_tag>
+ : public detail::within::use_relate
+{};
+
+template <typename Ring, typename MultiPolygon>
+struct within<Ring, MultiPolygon, ring_tag, multi_polygon_tag>
+ : public detail::within::use_relate
+{};
+
+template <typename MultiPolygon, typename Ring>
+struct within<MultiPolygon, Ring, multi_polygon_tag, ring_tag>
+ : public detail::within::use_relate
+{};
+
+template <typename Polygon, typename MultiPolygon>
+struct within<Polygon, MultiPolygon, polygon_tag, multi_polygon_tag>
+ : public detail::within::use_relate
+{};
+
+template <typename MultiPolygon, typename Polygon>
+struct within<MultiPolygon, Polygon, multi_polygon_tag, polygon_tag>
+ : public detail::within::use_relate
+{};
+
+template <typename MultiPolygon1, typename MultiPolygon2>
+struct within<MultiPolygon1, MultiPolygon2, multi_polygon_tag, multi_polygon_tag>
+ : public detail::within::use_relate
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+#include <boost/geometry/index/rtree.hpp>
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_IMPLEMENTATION_HPP
diff --git a/boost/geometry/algorithms/detail/within/interface.hpp b/boost/geometry/algorithms/detail/within/interface.hpp
new file mode 100644
index 0000000000..23263604c2
--- /dev/null
+++ b/boost/geometry/algorithms/detail/within/interface.hpp
@@ -0,0 +1,304 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// This file was modified by Oracle on 2013, 2014, 2017.
+// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the 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_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_INTERFACE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_INTERFACE_HPP
+
+
+#include <boost/concept_check.hpp>
+
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tag_cast.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/strategies/concepts/within_concept.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/strategies/within.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Tag1 = typename tag<Geometry1>::type,
+ typename Tag2 = typename tag<Geometry2>::type
+>
+struct within
+ : not_implemented<Tag1, Tag2>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+namespace resolve_strategy
+{
+
+struct within
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ concepts::within::check
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
+ Strategy
+ >();
+
+ return dispatch::within<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
+ }
+
+ template <typename Geometry1, typename Geometry2>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ default_strategy)
+ {
+ typedef typename strategy::within::services::default_strategy
+ <
+ Geometry1,
+ Geometry2
+ >::type strategy_type;
+
+ return apply(geometry1, geometry2, strategy_type());
+ }
+};
+
+} // namespace resolve_strategy
+
+
+namespace resolve_variant
+{
+
+template <typename Geometry1, typename Geometry2>
+struct within
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ concepts::check<Geometry1 const>();
+ concepts::check<Geometry2 const>();
+ assert_dimension_equal<Geometry1, Geometry2>();
+
+ return resolve_strategy::within::apply(geometry1,
+ geometry2,
+ strategy);
+ }
+};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
+struct within<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+{
+ template <typename Strategy>
+ struct visitor: boost::static_visitor<bool>
+ {
+ Geometry2 const& m_geometry2;
+ Strategy const& m_strategy;
+
+ visitor(Geometry2 const& geometry2, Strategy const& strategy)
+ : m_geometry2(geometry2)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry1>
+ bool operator()(Geometry1 const& geometry1) const
+ {
+ return within<Geometry1, Geometry2>::apply(geometry1,
+ m_geometry2,
+ m_strategy);
+ }
+ };
+
+ template <typename Strategy>
+ static inline bool
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ return boost::apply_visitor(visitor<Strategy>(geometry2, strategy),
+ geometry1);
+ }
+};
+
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct within<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ template <typename Strategy>
+ struct visitor: boost::static_visitor<bool>
+ {
+ Geometry1 const& m_geometry1;
+ Strategy const& m_strategy;
+
+ visitor(Geometry1 const& geometry1, Strategy const& strategy)
+ : m_geometry1(geometry1)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry2>
+ bool operator()(Geometry2 const& geometry2) const
+ {
+ return within<Geometry1, Geometry2>::apply(m_geometry1,
+ geometry2,
+ m_strategy);
+ }
+ };
+
+ template <typename Strategy>
+ static inline bool
+ apply(Geometry1 const& geometry1,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
+ Strategy const& strategy)
+ {
+ return boost::apply_visitor(visitor<Strategy>(geometry1, strategy),
+ geometry2
+ );
+ }
+};
+
+template <
+ BOOST_VARIANT_ENUM_PARAMS(typename T1),
+ BOOST_VARIANT_ENUM_PARAMS(typename T2)
+>
+struct within<
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
+>
+{
+ template <typename Strategy>
+ struct visitor: boost::static_visitor<bool>
+ {
+ Strategy const& m_strategy;
+
+ visitor(Strategy const& strategy): m_strategy(strategy) {}
+
+ template <typename Geometry1, typename Geometry2>
+ bool operator()(Geometry1 const& geometry1,
+ Geometry2 const& geometry2) const
+ {
+ return within<Geometry1, Geometry2>::apply(geometry1,
+ geometry2,
+ m_strategy);
+ }
+ };
+
+ template <typename Strategy>
+ static inline bool
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
+ Strategy const& strategy)
+ {
+ return boost::apply_visitor(visitor<Strategy>(strategy),
+ geometry1,
+ geometry2);
+ }
+};
+
+}
+
+
+/*!
+\brief \brief_check12{is completely inside}
+\ingroup within
+\details \details_check12{within, is completely inside}.
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry which might be within the second geometry
+\param geometry2 \param_geometry which might contain the first geometry
+\return true if geometry1 is completely contained within geometry2,
+ else false
+\note The default strategy is used for within detection
+
+
+\qbk{[include reference/algorithms/within.qbk]}
+
+\qbk{
+[heading Example]
+[within]
+[within_output]
+}
+ */
+template<typename Geometry1, typename Geometry2>
+inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ return resolve_variant::within
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, default_strategy());
+}
+
+/*!
+\brief \brief_check12{is completely inside} \brief_strategy
+\ingroup within
+\details \details_check12{within, is completely inside}, \brief_strategy. \details_strategy_reasons
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry which might be within the second geometry
+\param geometry2 \param_geometry which might contain the first geometry
+\param strategy strategy to be used
+\return true if geometry1 is completely contained within geometry2,
+ else false
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/within.qbk]}
+\qbk{
+[heading Available Strategies]
+\* [link geometry.reference.strategies.strategy_within_winding Winding (coordinate system agnostic)]
+\* [link geometry.reference.strategies.strategy_within_franklin Franklin (cartesian)]
+\* [link geometry.reference.strategies.strategy_within_crossings_multiply Crossings Multiply (cartesian)]
+
+[heading Example]
+[within_strategy]
+[within_strategy_output]
+
+}
+*/
+template<typename Geometry1, typename Geometry2, typename Strategy>
+inline bool within(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ return resolve_variant::within
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_INTERFACE_HPP
diff --git a/boost/geometry/algorithms/detail/within/multi_point.hpp b/boost/geometry/algorithms/detail/within/multi_point.hpp
new file mode 100644
index 0000000000..7e85f33383
--- /dev/null
+++ b/boost/geometry/algorithms/detail/within/multi_point.hpp
@@ -0,0 +1,268 @@
+// Boost.Geometry
+
+// Copyright (c) 2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the 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_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_MULTI_POINT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_MULTI_POINT_HPP
+
+
+#include <algorithm>
+#include <vector>
+
+#include <boost/range.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
+#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
+#include <boost/geometry/algorithms/detail/relate/less.hpp>
+#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
+#include <boost/geometry/algorithms/envelope.hpp>
+#include <boost/geometry/algorithms/detail/partition.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tag_cast.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/geometries/box.hpp>
+
+#include <boost/geometry/index/rtree.hpp>
+
+#include <boost/geometry/strategies/covered_by.hpp>
+#include <boost/geometry/strategies/disjoint.hpp>
+
+
+namespace boost { namespace geometry {
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace within {
+
+struct multi_point_point
+{
+ template <typename MultiPoint, typename Point, typename Strategy>
+ static inline bool apply(MultiPoint const& multi_point,
+ Point const& point,
+ Strategy const& strategy)
+ {
+ typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
+ for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
+ {
+ if (! strategy.apply(*it, point))
+ {
+ return false;
+ }
+ }
+
+ // all points of MultiPoint inside Point
+ return true;
+ }
+};
+
+// NOTE: currently the strategy is ignored, math::equals() is used inside relate::less
+struct multi_point_multi_point
+{
+ template <typename MultiPoint1, typename MultiPoint2, typename Strategy>
+ static inline bool apply(MultiPoint1 const& multi_point1,
+ MultiPoint2 const& multi_point2,
+ Strategy const& /*strategy*/)
+ {
+ typedef typename boost::range_value<MultiPoint2>::type point2_type;
+
+ relate::less const less = relate::less();
+
+ std::vector<point2_type> points2(boost::begin(multi_point2), boost::end(multi_point2));
+ std::sort(points2.begin(), points2.end(), less);
+
+ bool result = false;
+
+ typedef typename boost::range_const_iterator<MultiPoint1>::type iterator;
+ for ( iterator it = boost::begin(multi_point1) ; it != boost::end(multi_point1) ; ++it )
+ {
+ if (! std::binary_search(points2.begin(), points2.end(), *it, less))
+ {
+ return false;
+ }
+ else
+ {
+ result = true;
+ }
+ }
+
+ return result;
+ }
+};
+
+
+// TODO: the complexity could be lesser
+// the second geometry could be "prepared"/sorted
+// For Linear geometries partition could be used
+// For Areal geometries point_in_geometry() would have to call the winding
+// strategy differently, currently it linearly calls the strategy for each
+// segment. So the segments would have to be sorted in a way consistent with
+// the strategy and then the strategy called only for the segments in range.
+template <bool Within>
+struct multi_point_single_geometry
+{
+ template <typename MultiPoint, typename LinearOrAreal, typename Strategy>
+ static inline bool apply(MultiPoint const& multi_point,
+ LinearOrAreal const& linear_or_areal,
+ Strategy const& strategy)
+ {
+ typedef typename boost::range_value<MultiPoint>::type point1_type;
+ typedef typename point_type<LinearOrAreal>::type point2_type;
+ typedef model::box<point2_type> box2_type;
+
+ // Create envelope of geometry
+ box2_type box;
+ geometry::envelope(linear_or_areal, box, strategy.get_envelope_strategy());
+ geometry::detail::expand_by_epsilon(box);
+
+ typedef typename strategy::covered_by::services::default_strategy
+ <
+ point1_type, box2_type
+ >::type point_in_box_type;
+
+ // Test each Point with envelope and then geometry if needed
+ // If in the exterior, break
+ bool result = false;
+
+ typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
+ for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
+ {
+ int in_val = 0;
+
+ // exterior of box and of geometry
+ if (! point_in_box_type::apply(*it, box)
+ || (in_val = point_in_geometry(*it, linear_or_areal, strategy)) < 0)
+ {
+ result = false;
+ break;
+ }
+
+ // interior : interior/boundary
+ if (Within ? in_val > 0 : in_val >= 0)
+ {
+ result = true;
+ }
+ }
+
+ return result;
+ }
+};
+
+
+// TODO: same here, probably the complexity could be lesser
+template <bool Within>
+struct multi_point_multi_geometry
+{
+ template <typename MultiPoint, typename LinearOrAreal, typename Strategy>
+ static inline bool apply(MultiPoint const& multi_point,
+ LinearOrAreal const& linear_or_areal,
+ Strategy const& strategy)
+ {
+ typedef typename point_type<LinearOrAreal>::type point2_type;
+ typedef model::box<point2_type> box2_type;
+ static const bool is_linear = is_same
+ <
+ typename tag_cast
+ <
+ typename tag<LinearOrAreal>::type,
+ linear_tag
+ >::type,
+ linear_tag
+ >::value;
+
+ typename Strategy::envelope_strategy_type const
+ envelope_strategy = strategy.get_envelope_strategy();
+
+ // TODO: box pairs could be constructed on the fly, inside the rtree
+
+ // Prepare range of envelopes and ids
+ std::size_t count2 = boost::size(linear_or_areal);
+ typedef std::pair<box2_type, std::size_t> box_pair_type;
+ typedef std::vector<box_pair_type> box_pair_vector;
+ box_pair_vector boxes(count2);
+ for (std::size_t i = 0 ; i < count2 ; ++i)
+ {
+ geometry::envelope(linear_or_areal, boxes[i].first, envelope_strategy);
+ geometry::detail::expand_by_epsilon(boxes[i].first);
+ boxes[i].second = i;
+ }
+
+ // Create R-tree
+ index::rtree<box_pair_type, index::rstar<4> > rtree(boxes.begin(), boxes.end());
+
+ // For each point find overlapping envelopes and test corresponding single geometries
+ // If a point is in the exterior break
+ bool result = false;
+
+ typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
+ for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
+ {
+ // TODO: investigate the possibility of using satisfies
+ // TODO: investigate the possibility of using iterative queries (optimization below)
+ box_pair_vector inters_boxes;
+ rtree.query(index::intersects(*it), std::back_inserter(inters_boxes));
+
+ bool found_interior = false;
+ bool found_boundary = false;
+ int boundaries = 0;
+
+ typedef typename box_pair_vector::const_iterator iterator;
+ for ( iterator box_it = inters_boxes.begin() ; box_it != inters_boxes.end() ; ++box_it )
+ {
+ int in_val = point_in_geometry(*it, range::at(linear_or_areal, box_it->second), strategy);
+
+ if (in_val > 0)
+ found_interior = true;
+ else if (in_val == 0)
+ ++boundaries;
+
+ // If the result was set previously (interior or
+ // interior/boundary found) the only thing that needs to be
+ // done for other points is to make sure they're not
+ // overlapping the exterior no need to analyse boundaries.
+ if (result && in_val >= 0)
+ {
+ break;
+ }
+ }
+
+ if ( boundaries > 0)
+ {
+ if (is_linear && boundaries % 2 == 0)
+ found_interior = true;
+ else
+ found_boundary = true;
+ }
+
+ // exterior
+ if (! found_interior && ! found_boundary)
+ {
+ result = false;
+ break;
+ }
+
+ // interior : interior/boundary
+ if (Within ? found_interior : (found_interior || found_boundary))
+ {
+ result = true;
+ }
+ }
+
+ return result;
+ }
+};
+
+}} // namespace detail::within
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_MULTI_POINT_HPP
diff --git a/boost/geometry/algorithms/equals.hpp b/boost/geometry/algorithms/equals.hpp
index 1479ea66fa..77b8977d22 100644
--- a/boost/geometry/algorithms/equals.hpp
+++ b/boost/geometry/algorithms/equals.hpp
@@ -22,649 +22,8 @@
#define BOOST_GEOMETRY_ALGORITHMS_EQUALS_HPP
-#include <cstddef>
-#include <vector>
-
-#include <boost/range.hpp>
-#include <boost/type_traits/is_base_of.hpp>
-
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
-#include <boost/geometry/core/access.hpp>
-#include <boost/geometry/core/coordinate_dimension.hpp>
-#include <boost/geometry/core/geometry_id.hpp>
-#include <boost/geometry/core/reverse_dispatch.hpp>
-#include <boost/geometry/core/tags.hpp>
-
-#include <boost/geometry/geometries/concepts/check.hpp>
-
-#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
-#include <boost/geometry/algorithms/not_implemented.hpp>
-
-// For trivial checks
-#include <boost/geometry/algorithms/area.hpp>
-#include <boost/geometry/algorithms/length.hpp>
-#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/select_coordinate_type.hpp>
-#include <boost/geometry/util/select_most_precise.hpp>
-
-#include <boost/geometry/algorithms/detail/equals/collect_vectors.hpp>
-#include <boost/geometry/algorithms/relate.hpp>
-#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
-
-#include <boost/geometry/views/detail/indexed_point_view.hpp>
-
-
-namespace boost { namespace geometry
-{
-
-#ifndef DOXYGEN_NO_DETAIL
-namespace detail { namespace equals
-{
-
-
-template
-<
- std::size_t Dimension,
- std::size_t DimensionCount
->
-struct point_point
-{
- template <typename Point1, typename Point2, typename Strategy>
- static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& strategy)
- {
- return ! detail::disjoint::point_point
- <
- Point1, Point2,
- Dimension, DimensionCount
- >::apply(point1, point2, strategy);
- }
-};
-
-
-template
-<
- std::size_t Dimension,
- std::size_t DimensionCount
->
-struct box_box
-{
- template <typename Box1, typename Box2, typename Strategy>
- static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
- {
- if (!geometry::math::equals(get<min_corner, Dimension>(box1), get<min_corner, Dimension>(box2))
- || !geometry::math::equals(get<max_corner, Dimension>(box1), get<max_corner, Dimension>(box2)))
- {
- return false;
- }
- return box_box<Dimension + 1, DimensionCount>::apply(box1, box2, strategy);
- }
-};
-
-template <std::size_t DimensionCount>
-struct box_box<DimensionCount, DimensionCount>
-{
- template <typename Box1, typename Box2, typename Strategy>
- static inline bool apply(Box1 const& , Box2 const& , Strategy const& )
- {
- return true;
- }
-};
-
-
-struct segment_segment
-{
- template <typename Segment1, typename Segment2, typename Strategy>
- static inline bool apply(Segment1 const& segment1, Segment2 const& segment2, Strategy const& )
- {
- return equals::equals_point_point(
- indexed_point_view<Segment1 const, 0>(segment1),
- indexed_point_view<Segment2 const, 0>(segment2) )
- ? equals::equals_point_point(
- indexed_point_view<Segment1 const, 1>(segment1),
- indexed_point_view<Segment2 const, 1>(segment2) )
- : ( equals::equals_point_point(
- indexed_point_view<Segment1 const, 0>(segment1),
- indexed_point_view<Segment2 const, 1>(segment2) )
- && equals::equals_point_point(
- indexed_point_view<Segment1 const, 1>(segment1),
- indexed_point_view<Segment2 const, 0>(segment2) )
- );
- }
-};
-
-
-struct area_check
-{
- template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- return geometry::math::equals(
- geometry::area(geometry1,
- strategy.template get_area_strategy<Geometry1>()),
- geometry::area(geometry2,
- strategy.template get_area_strategy<Geometry2>()));
- }
-};
-
-
-struct length_check
-{
- template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- return geometry::math::equals(
- geometry::length(geometry1,
- strategy.template get_distance_strategy<Geometry1>()),
- geometry::length(geometry2,
- strategy.template get_distance_strategy<Geometry2>()));
- }
-};
-
-
-template <typename Geometry1, typename Geometry2, typename IntersectionStrategy>
-struct collected_vector
-{
- typedef typename geometry::select_most_precise
- <
- typename select_coordinate_type
- <
- Geometry1, Geometry2
- >::type,
- double
- >::type calculation_type;
-
- typedef geometry::collected_vector
- <
- calculation_type,
- Geometry1,
- typename IntersectionStrategy::side_strategy_type
- > type;
-};
-
-template <typename TrivialCheck>
-struct equals_by_collection
-{
- template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- if (! TrivialCheck::apply(geometry1, geometry2, strategy))
- {
- return false;
- }
-
- typedef typename collected_vector
- <
- Geometry1, Geometry2, Strategy
- >::type collected_vector_type;
-
- std::vector<collected_vector_type> c1, c2;
-
- geometry::collect_vectors(c1, geometry1);
- geometry::collect_vectors(c2, geometry2);
-
- if (boost::size(c1) != boost::size(c2))
- {
- return false;
- }
-
- std::sort(c1.begin(), c1.end());
- std::sort(c2.begin(), c2.end());
-
- // Just check if these vectors are equal.
- return std::equal(c1.begin(), c1.end(), c2.begin());
- }
-};
-
-template<typename Geometry1, typename Geometry2>
-struct equals_by_relate
- : detail::relate::relate_impl
- <
- detail::de9im::static_mask_equals_type,
- Geometry1,
- Geometry2
- >
-{};
-
-// If collect_vectors which is a SideStrategy-dispatched optimization
-// is implemented in a way consistent with the Intersection/Side Strategy
-// then collect_vectors is used, otherwise relate is used.
-// NOTE: the result could be coneptually different for invalid
-// geometries in different coordinate systems because collect_vectors
-// and relate treat invalid geometries differently.
-template<typename TrivialCheck>
-struct equals_by_collection_or_relate
-{
- template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- typedef typename boost::is_base_of
- <
- nyi::not_implemented_tag,
- typename collected_vector
- <
- Geometry1, Geometry2, Strategy
- >::type
- >::type enable_relate_type;
-
- return apply(geometry1, geometry2, strategy, enable_relate_type());
- }
-
-private:
- template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy,
- boost::false_type /*enable_relate*/)
- {
- return equals_by_collection<TrivialCheck>::apply(geometry1, geometry2, strategy);
- }
-
- template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy,
- boost::true_type /*enable_relate*/)
- {
- return equals_by_relate<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
- }
-};
-
-
-}} // namespace detail::equals
-#endif // DOXYGEN_NO_DETAIL
-
-
-#ifndef DOXYGEN_NO_DISPATCH
-namespace dispatch
-{
-
-template
-<
- typename Geometry1,
- typename Geometry2,
- typename Tag1 = typename tag<Geometry1>::type,
- typename Tag2 = typename tag<Geometry2>::type,
- std::size_t DimensionCount = dimension<Geometry1>::type::value,
- bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
->
-struct equals: not_implemented<Tag1, Tag2>
-{};
-
-
-// If reversal is needed, perform it
-template
-<
- typename Geometry1, typename Geometry2,
- typename Tag1, typename Tag2,
- std::size_t DimensionCount
->
-struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true>
- : equals<Geometry2, Geometry1, Tag2, Tag1, DimensionCount, false>
-{
- template <typename Strategy>
- static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
- {
- return equals
- <
- Geometry2, Geometry1,
- Tag2, Tag1,
- DimensionCount,
- false
- >::apply(g2, g1, strategy);
- }
-};
-
-
-template <typename P1, typename P2, std::size_t DimensionCount, bool Reverse>
-struct equals<P1, P2, point_tag, point_tag, DimensionCount, Reverse>
- : detail::equals::point_point<0, DimensionCount>
-{};
-
-template <typename MultiPoint1, typename MultiPoint2, std::size_t DimensionCount, bool Reverse>
-struct equals<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag, DimensionCount, Reverse>
- : detail::equals::equals_by_relate<MultiPoint1, MultiPoint2>
-{};
-
-template <typename MultiPoint, typename Point, std::size_t DimensionCount, bool Reverse>
-struct equals<MultiPoint, Point, multi_point_tag, point_tag, DimensionCount, Reverse>
- : detail::equals::equals_by_relate<MultiPoint, Point>
-{};
-
-template <typename MultiPoint, typename Point, std::size_t DimensionCount, bool Reverse>
-struct equals<Point, MultiPoint, point_tag, multi_point_tag, DimensionCount, Reverse>
- : detail::equals::equals_by_relate<Point, MultiPoint>
-{};
-
-template <typename Box1, typename Box2, std::size_t DimensionCount, bool Reverse>
-struct equals<Box1, Box2, box_tag, box_tag, DimensionCount, Reverse>
- : detail::equals::box_box<0, DimensionCount>
-{};
-
-
-template <typename Ring1, typename Ring2, bool Reverse>
-struct equals<Ring1, Ring2, ring_tag, ring_tag, 2, Reverse>
- : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
-{};
-
-
-template <typename Polygon1, typename Polygon2, bool Reverse>
-struct equals<Polygon1, Polygon2, polygon_tag, polygon_tag, 2, Reverse>
- : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
-{};
-
-
-template <typename Polygon, typename Ring, bool Reverse>
-struct equals<Polygon, Ring, polygon_tag, ring_tag, 2, Reverse>
- : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
-{};
-
-
-template <typename Ring, typename Box, bool Reverse>
-struct equals<Ring, Box, ring_tag, box_tag, 2, Reverse>
- : detail::equals::equals_by_collection<detail::equals::area_check>
-{};
-
-
-template <typename Polygon, typename Box, bool Reverse>
-struct equals<Polygon, Box, polygon_tag, box_tag, 2, Reverse>
- : detail::equals::equals_by_collection<detail::equals::area_check>
-{};
-
-template <typename Segment1, typename Segment2, std::size_t DimensionCount, bool Reverse>
-struct equals<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, Reverse>
- : detail::equals::segment_segment
-{};
-
-template <typename LineString1, typename LineString2, bool Reverse>
-struct equals<LineString1, LineString2, linestring_tag, linestring_tag, 2, Reverse>
- : detail::equals::equals_by_relate<LineString1, LineString2>
-{};
-
-template <typename LineString, typename MultiLineString, bool Reverse>
-struct equals<LineString, MultiLineString, linestring_tag, multi_linestring_tag, 2, Reverse>
- : detail::equals::equals_by_relate<LineString, MultiLineString>
-{};
-
-template <typename MultiLineString1, typename MultiLineString2, bool Reverse>
-struct equals<MultiLineString1, MultiLineString2, multi_linestring_tag, multi_linestring_tag, 2, Reverse>
- : detail::equals::equals_by_relate<MultiLineString1, MultiLineString2>
-{};
-
-
-template <typename MultiPolygon1, typename MultiPolygon2, bool Reverse>
-struct equals
- <
- MultiPolygon1, MultiPolygon2,
- multi_polygon_tag, multi_polygon_tag,
- 2,
- Reverse
- >
- : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
-{};
-
-
-template <typename Polygon, typename MultiPolygon, bool Reverse>
-struct equals
- <
- Polygon, MultiPolygon,
- polygon_tag, multi_polygon_tag,
- 2,
- Reverse
- >
- : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
-{};
-
-template <typename MultiPolygon, typename Ring, bool Reverse>
-struct equals
- <
- MultiPolygon, Ring,
- multi_polygon_tag, ring_tag,
- 2,
- Reverse
- >
- : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
-{};
-
-
-} // namespace dispatch
-#endif // DOXYGEN_NO_DISPATCH
-
-
-namespace resolve_strategy
-{
-
-struct equals
-{
- template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- return dispatch::equals
- <
- Geometry1, Geometry2
- >::apply(geometry1, geometry2, strategy);
- }
-
- template <typename Geometry1, typename Geometry2>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- default_strategy)
- {
- typedef typename strategy::relate::services::default_strategy
- <
- Geometry1,
- Geometry2
- >::type strategy_type;
-
- return dispatch::equals
- <
- Geometry1, Geometry2
- >::apply(geometry1, geometry2, strategy_type());
- }
-};
-
-} // namespace resolve_strategy
-
-
-namespace resolve_variant {
-
-template <typename Geometry1, typename Geometry2>
-struct equals
-{
- template <typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- concepts::check_concepts_and_equal_dimensions
- <
- Geometry1 const,
- Geometry2 const
- >();
-
- return resolve_strategy::equals
- ::apply(geometry1, geometry2, strategy);
- }
-};
-
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct equals<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
-{
- template <typename Strategy>
- struct visitor: static_visitor<bool>
- {
- Geometry2 const& m_geometry2;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2, Strategy const& strategy)
- : m_geometry2(geometry2)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry1>
- inline bool operator()(Geometry1 const& geometry1) const
- {
- return equals<Geometry1, Geometry2>
- ::apply(geometry1, m_geometry2, m_strategy);
- }
-
- };
-
- template <typename Strategy>
- static inline bool apply(
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy
- )
- {
- return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
- }
-};
-
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct equals<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
-{
- template <typename Strategy>
- struct visitor: static_visitor<bool>
- {
- Geometry1 const& m_geometry1;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1, Strategy const& strategy)
- : m_geometry1(geometry1)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry2>
- inline bool operator()(Geometry2 const& geometry2) const
- {
- return equals<Geometry1, Geometry2>
- ::apply(m_geometry1, geometry2, m_strategy);
- }
-
- };
-
- template <typename Strategy>
- static inline bool apply(
- Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Strategy const& strategy
- )
- {
- return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
- }
-};
-
-template <
- BOOST_VARIANT_ENUM_PARAMS(typename T1),
- BOOST_VARIANT_ENUM_PARAMS(typename T2)
->
-struct equals<
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
->
-{
- template <typename Strategy>
- struct visitor: static_visitor<bool>
- {
- Strategy const& m_strategy;
-
- visitor(Strategy const& strategy)
- : m_strategy(strategy)
- {}
-
- template <typename Geometry1, typename Geometry2>
- inline bool operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
- {
- return equals<Geometry1, Geometry2>
- ::apply(geometry1, geometry2, m_strategy);
- }
-
- };
-
- template <typename Strategy>
- static inline bool apply(
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Strategy const& strategy
- )
- {
- return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
- }
-};
-
-} // namespace resolve_variant
-
-
-/*!
-\brief \brief_check{are spatially equal}
-\details \details_check12{equals, is spatially equal}. Spatially equal means
- that the same point set is included. A box can therefore be spatially equal
- to a ring or a polygon, or a linestring can be spatially equal to a
- multi-linestring or a segment. This only works theoretically, not all
- combinations are implemented yet.
-\ingroup equals
-\tparam Geometry1 \tparam_geometry
-\tparam Geometry2 \tparam_geometry
-\tparam Strategy \tparam_strategy{Equals}
-\param geometry1 \param_geometry
-\param geometry2 \param_geometry
-\param strategy \param_strategy{equals}
-\return \return_check2{are spatially equal}
-
-\qbk{distinguish,with strategy}
-\qbk{[include reference/algorithms/equals.qbk]}
- */
-template <typename Geometry1, typename Geometry2, typename Strategy>
-inline bool equals(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
-{
- return resolve_variant::equals
- <
- Geometry1, Geometry2
- >::apply(geometry1, geometry2, strategy);
-}
-
-
-/*!
-\brief \brief_check{are spatially equal}
-\details \details_check12{equals, is spatially equal}. Spatially equal means
- that the same point set is included. A box can therefore be spatially equal
- to a ring or a polygon, or a linestring can be spatially equal to a
- multi-linestring or a segment. This only works theoretically, not all
- combinations are implemented yet.
-\ingroup equals
-\tparam Geometry1 \tparam_geometry
-\tparam Geometry2 \tparam_geometry
-\param geometry1 \param_geometry
-\param geometry2 \param_geometry
-\return \return_check2{are spatially equal}
-
-\qbk{[include reference/algorithms/equals.qbk]}
- */
-template <typename Geometry1, typename Geometry2>
-inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2)
-{
- return resolve_variant::equals<Geometry1, Geometry2>
- ::apply(geometry1, geometry2, default_strategy());
-}
-
-
-}} // namespace boost::geometry
+#include <boost/geometry/algorithms/detail/equals/interface.hpp>
+#include <boost/geometry/algorithms/detail/equals/implementation.hpp>
#endif // BOOST_GEOMETRY_ALGORITHMS_EQUALS_HPP
diff --git a/boost/geometry/algorithms/intersects.hpp b/boost/geometry/algorithms/intersects.hpp
index 12ae169f12..503ee1a10a 100644
--- a/boost/geometry/algorithms/intersects.hpp
+++ b/boost/geometry/algorithms/intersects.hpp
@@ -21,120 +21,8 @@
#define BOOST_GEOMETRY_ALGORITHMS_INTERSECTS_HPP
-#include <deque>
+#include <boost/geometry/algorithms/detail/intersects/interface.hpp>
+#include <boost/geometry/algorithms/detail/intersects/implementation.hpp>
-#include <boost/geometry/geometries/concepts/check.hpp>
-#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
-#include <boost/geometry/algorithms/disjoint.hpp>
-
-#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
-#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
-
-#include <boost/geometry/strategies/relate.hpp>
-
-
-namespace boost { namespace geometry
-{
-
-/*!
-\brief \brief_check{has at least one intersection (crossing or self-tangency)}
-\note This function can be called for one geometry (self-intersection) and
- also for two geometries (intersection)
-\ingroup intersects
-\tparam Geometry \tparam_geometry
-\param geometry \param_geometry
-\return \return_check{is self-intersecting}
-
-\qbk{distinguish,one geometry}
-\qbk{[def __one_parameter__]}
-\qbk{[include reference/algorithms/intersects.qbk]}
-*/
-template <typename Geometry>
-inline bool intersects(Geometry const& geometry)
-{
- concepts::check<Geometry const>();
-
- typedef typename geometry::point_type<Geometry>::type point_type;
- typedef typename strategy::relate::services::default_strategy
- <
- Geometry, Geometry
- >::type strategy_type;
- typedef detail::no_rescale_policy rescale_policy_type;
-
- typedef detail::overlay::turn_info
- <
- point_type,
- typename segment_ratio_type<point_type, rescale_policy_type>::type
- > turn_info;
-
- std::deque<turn_info> turns;
-
- typedef detail::overlay::get_turn_info
- <
- detail::overlay::assign_null_policy
- > turn_policy;
-
- strategy_type strategy;
- rescale_policy_type robust_policy;
-
- detail::disjoint::disjoint_interrupt_policy policy;
- detail::self_get_turn_points::get_turns
- <
- turn_policy
- >::apply(geometry, strategy, robust_policy, turns, policy);
- return policy.has_intersections;
-}
-
-
-/*!
-\brief \brief_check2{have at least one intersection}
-\ingroup intersects
-\tparam Geometry1 \tparam_geometry
-\tparam Geometry2 \tparam_geometry
-\tparam Strategy \tparam_strategy{Intersects}
-\param geometry1 \param_geometry
-\param geometry2 \param_geometry
-\param strategy \param_strategy{intersects}
-\return \return_check2{intersect each other}
-
-\qbk{distinguish,with strategy}
-\qbk{[include reference/algorithms/intersects.qbk]}
- */
-template <typename Geometry1, typename Geometry2, typename Strategy>
-inline bool intersects(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
-{
- concepts::check<Geometry1 const>();
- concepts::check<Geometry2 const>();
-
- return ! geometry::disjoint(geometry1, geometry2, strategy);
-}
-
-
-/*!
-\brief \brief_check2{have at least one intersection}
-\ingroup intersects
-\tparam Geometry1 \tparam_geometry
-\tparam Geometry2 \tparam_geometry
-\param geometry1 \param_geometry
-\param geometry2 \param_geometry
-\return \return_check2{intersect each other}
-
-\qbk{distinguish,two geometries}
-\qbk{[include reference/algorithms/intersects.qbk]}
- */
-template <typename Geometry1, typename Geometry2>
-inline bool intersects(Geometry1 const& geometry1, Geometry2 const& geometry2)
-{
- concepts::check<Geometry1 const>();
- concepts::check<Geometry2 const>();
-
- return ! geometry::disjoint(geometry1, geometry2);
-}
-
-
-
-}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_INTERSECTS_HPP
diff --git a/boost/geometry/algorithms/is_convex.hpp b/boost/geometry/algorithms/is_convex.hpp
index 8feb48db6a..4a9251b270 100644
--- a/boost/geometry/algorithms/is_convex.hpp
+++ b/boost/geometry/algorithms/is_convex.hpp
@@ -2,6 +2,11 @@
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -10,17 +15,23 @@
#define BOOST_GEOMETRY_ALGORITHMS_IS_CONVEX_HPP
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
+
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/point_type.hpp>
-#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/iterators/ever_circling_iterator.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/side.hpp>
-#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/views/detail/normalized_view.hpp>
+
namespace boost { namespace geometry
{
@@ -31,15 +42,9 @@ namespace detail { namespace is_convex
struct ring_is_convex
{
- template <typename Ring>
- static inline bool apply(Ring const& ring)
+ template <typename Ring, typename SideStrategy>
+ static inline bool apply(Ring const& ring, SideStrategy const& strategy)
{
- typedef typename geometry::point_type<Ring>::type point_type;
- typedef typename strategy::side::services::default_strategy
- <
- typename cs_tag<point_type>::type
- >::type side_strategy_type;
-
std::size_t n = boost::size(ring);
if (boost::size(ring) < core_detail::closure::minimum_ring_size
<
@@ -86,7 +91,7 @@ struct ring_is_convex
// iterator
for (std::size_t i = 0; i < n; i++)
{
- int const side = side_strategy_type::apply(*previous, *current, *next);
+ int const side = strategy.apply(*previous, *current, *next);
if (side == 1)
{
// Next is on the left side of clockwise ring:
@@ -129,7 +134,8 @@ struct is_convex : not_implemented<Tag>
template <typename Box>
struct is_convex<Box, box_tag>
{
- static inline bool apply(Box const& )
+ template <typename Strategy>
+ static inline bool apply(Box const& , Strategy const& )
{
// Any box is convex (TODO: consider spherical boxes)
return true;
@@ -144,13 +150,71 @@ struct is_convex<Box, ring_tag> : detail::is_convex::ring_is_convex
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
-// TODO: variants
+namespace resolve_variant {
+
+template <typename Geometry>
+struct is_convex
+{
+ template <typename Strategy>
+ static bool apply(Geometry const& geometry, Strategy const& strategy)
+ {
+ concepts::check<Geometry>();
+ return dispatch::is_convex<Geometry>::apply(geometry, strategy);
+ }
+
+ static bool apply(Geometry const& geometry, geometry::default_strategy const&)
+ {
+ typedef typename strategy::side::services::default_strategy
+ <
+ typename cs_tag<Geometry>::type
+ >::type side_strategy;
+
+ return apply(geometry, side_strategy());
+ }
+};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct is_convex<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ template <typename Strategy>
+ struct visitor: boost::static_visitor<bool>
+ {
+ Strategy const& m_strategy;
+
+ visitor(Strategy const& strategy) : m_strategy(strategy) {}
+
+ template <typename Geometry>
+ bool operator()(Geometry const& geometry) const
+ {
+ return is_convex<Geometry>::apply(geometry, m_strategy);
+ }
+ };
+
+ template <typename Strategy>
+ static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
+ Strategy const& strategy)
+ {
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry);
+ }
+};
+
+} // namespace resolve_variant
// TODO: documentation / qbk
template<typename Geometry>
inline bool is_convex(Geometry const& geometry)
{
- return dispatch::is_convex<Geometry>::apply(geometry);
+ return resolve_variant::is_convex
+ <
+ Geometry
+ >::apply(geometry, geometry::default_strategy());
+}
+
+// TODO: documentation / qbk
+template<typename Geometry, typename Strategy>
+inline bool is_convex(Geometry const& geometry, Strategy const& strategy)
+{
+ return resolve_variant::is_convex<Geometry>::apply(geometry, strategy);
}
diff --git a/boost/geometry/algorithms/overlaps.hpp b/boost/geometry/algorithms/overlaps.hpp
index bedf17599b..869a85ca98 100644
--- a/boost/geometry/algorithms/overlaps.hpp
+++ b/boost/geometry/algorithms/overlaps.hpp
@@ -20,214 +20,8 @@
#define BOOST_GEOMETRY_ALGORITHMS_OVERLAPS_HPP
-#include <cstddef>
+#include <boost/geometry/algorithms/detail/overlaps/interface.hpp>
+#include <boost/geometry/algorithms/detail/overlaps/implementation.hpp>
-#include <boost/geometry/core/access.hpp>
-
-#include <boost/geometry/algorithms/not_implemented.hpp>
-
-#include <boost/geometry/geometries/concepts/check.hpp>
-
-#include <boost/geometry/algorithms/relate.hpp>
-#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
-
-
-namespace boost { namespace geometry
-{
-
-#ifndef DOXYGEN_NO_DETAIL
-namespace detail { namespace overlaps
-{
-
-template
-<
- std::size_t Dimension,
- std::size_t DimensionCount
->
-struct box_box_loop
-{
- template <typename Box1, typename Box2>
- static inline void apply(Box1 const& b1, Box2 const& b2,
- bool& overlaps, bool& one_in_two, bool& two_in_one)
- {
- assert_dimension_equal<Box1, Box2>();
-
- typedef typename coordinate_type<Box1>::type coordinate_type1;
- typedef typename coordinate_type<Box2>::type coordinate_type2;
-
- coordinate_type1 const& min1 = get<min_corner, Dimension>(b1);
- coordinate_type1 const& max1 = get<max_corner, Dimension>(b1);
- coordinate_type2 const& min2 = get<min_corner, Dimension>(b2);
- coordinate_type2 const& max2 = get<max_corner, Dimension>(b2);
-
- // We might use the (not yet accepted) Boost.Interval
- // submission in the future
-
- // If:
- // B1: |-------|
- // B2: |------|
- // in any dimension -> no overlap
- if (max1 <= min2 || min1 >= max2)
- {
- overlaps = false;
- return;
- }
-
- // If:
- // B1: |--------------------|
- // B2: |-------------|
- // in all dimensions -> within, then no overlap
- // B1: |--------------------|
- // B2: |-------------|
- // this is "within-touch" -> then no overlap. So use < and >
- if (min1 < min2 || max1 > max2)
- {
- one_in_two = false;
- }
-
- // Same other way round
- if (min2 < min1 || max2 > max1)
- {
- two_in_one = false;
- }
-
- box_box_loop
- <
- Dimension + 1,
- DimensionCount
- >::apply(b1, b2, overlaps, one_in_two, two_in_one);
- }
-};
-
-template
-<
- std::size_t DimensionCount
->
-struct box_box_loop<DimensionCount, DimensionCount>
-{
- template <typename Box1, typename Box2>
- static inline void apply(Box1 const& , Box2 const&, bool&, bool&, bool&)
- {
- }
-};
-
-struct box_box
-{
- template <typename Box1, typename Box2, typename Strategy>
- static inline bool apply(Box1 const& b1, Box2 const& b2, Strategy const& /*strategy*/)
- {
- bool overlaps = true;
- bool within1 = true;
- bool within2 = true;
- box_box_loop
- <
- 0,
- dimension<Box1>::type::value
- >::apply(b1, b2, overlaps, within1, within2);
-
- /*
- \see http://docs.codehaus.org/display/GEOTDOC/02+Geometry+Relationships#02GeometryRelationships-Overlaps
- where is stated that "inside" is not an "overlap",
- this is true and is implemented as such.
- */
- return overlaps && ! within1 && ! within2;
- }
-};
-
-}} // namespace detail::overlaps
-#endif // DOXYGEN_NO_DETAIL
-
-
-#ifndef DOXYGEN_NO_DISPATCH
-namespace dispatch
-{
-
-
-template
-<
- typename Geometry1,
- typename Geometry2,
- typename Tag1 = typename tag<Geometry1>::type,
- typename Tag2 = typename tag<Geometry2>::type
->
-struct overlaps
- : detail::relate::relate_impl
- <
- detail::de9im::static_mask_overlaps_type,
- Geometry1,
- Geometry2
- >
-{};
-
-
-template <typename Box1, typename Box2>
-struct overlaps<Box1, Box2, box_tag, box_tag>
- : detail::overlaps::box_box
-{};
-
-} // namespace dispatch
-#endif // DOXYGEN_NO_DISPATCH
-
-
-/*!
-\brief \brief_check2{overlap}
-\ingroup overlaps
-\tparam Geometry1 \tparam_geometry
-\tparam Geometry2 \tparam_geometry
-\tparam Strategy \tparam_strategy{Overlaps}
-\param geometry1 \param_geometry
-\param geometry2 \param_geometry
-\param strategy \param_strategy{overlaps}
-\return \return_check2{overlap}
-
-\qbk{distinguish,with strategy}
-\qbk{[include reference/algorithms/overlaps.qbk]}
-*/
-template <typename Geometry1, typename Geometry2, typename Strategy>
-inline bool overlaps(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
-{
- concepts::check<Geometry1 const>();
- concepts::check<Geometry2 const>();
-
- return dispatch::overlaps
- <
- Geometry1,
- Geometry2
- >::apply(geometry1, geometry2, strategy);
-}
-
-/*!
-\brief \brief_check2{overlap}
-\ingroup overlaps
-\tparam Geometry1 \tparam_geometry
-\tparam Geometry2 \tparam_geometry
-\param geometry1 \param_geometry
-\param geometry2 \param_geometry
-\return \return_check2{overlap}
-
-\qbk{[include reference/algorithms/overlaps.qbk]}
-*/
-template <typename Geometry1, typename Geometry2>
-inline bool overlaps(Geometry1 const& geometry1, Geometry2 const& geometry2)
-{
- concepts::check<Geometry1 const>();
- concepts::check<Geometry2 const>();
-
- typedef typename strategy::relate::services::default_strategy
- <
- Geometry1,
- Geometry2
- >::type strategy_type;
-
- return dispatch::overlaps
- <
- Geometry1,
- Geometry2
- >::apply(geometry1, geometry2, strategy_type());
-}
-
-}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_OVERLAPS_HPP
diff --git a/boost/geometry/algorithms/point_on_surface.hpp b/boost/geometry/algorithms/point_on_surface.hpp
index e9041f937b..3f4d0f4afe 100644
--- a/boost/geometry/algorithms/point_on_surface.hpp
+++ b/boost/geometry/algorithms/point_on_surface.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2013 Mateusz Loskot, London, UK.
// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2014.
-// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -33,6 +33,7 @@
#include <boost/geometry/algorithms/detail/extreme_points.hpp>
#include <boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp>
+#include <boost/geometry/strategies/side.hpp>
namespace boost { namespace geometry
@@ -241,8 +242,9 @@ inline void replace_extremes_for_self_tangencies(Extremes& extremes, Intruders&
extremes = triangle;
}
-template <int Dimension, typename Geometry, typename Point>
-inline bool calculate_point_on_surface(Geometry const& geometry, Point& point)
+template <int Dimension, typename Geometry, typename Point, typename SideStrategy>
+inline bool calculate_point_on_surface(Geometry const& geometry, Point& point,
+ SideStrategy const& strategy)
{
typedef typename geometry::point_type<Geometry>::type point_type;
typedef typename geometry::coordinate_type<Geometry>::type coordinate_type;
@@ -250,7 +252,7 @@ inline bool calculate_point_on_surface(Geometry const& geometry, Point& point)
typedef std::vector<std::vector<point_type> > intruders_type;
intruders_type intruders;
- geometry::extreme_points<Dimension>(geometry, extremes, intruders);
+ geometry::extreme_points<Dimension>(geometry, extremes, intruders, strategy);
if (extremes.size() < 3)
{
@@ -291,22 +293,58 @@ inline bool calculate_point_on_surface(Geometry const& geometry, Point& point)
\tparam Geometry geometry type. This also defines the type of the output point
\param geometry Geometry to take point from
\param point Point to assign
+\param strategy side strategy
*/
-template <typename Geometry, typename Point>
-inline void point_on_surface(Geometry const& geometry, Point & point)
+template <typename Geometry, typename Point, typename SideStrategy>
+inline void point_on_surface(Geometry const& geometry, Point & point,
+ SideStrategy const& strategy)
{
concepts::check<Point>();
concepts::check<Geometry const>();
// First try in Y-direction (which should always succeed for valid polygons)
- if (! detail::point_on_surface::calculate_point_on_surface<1>(geometry, point))
+ if (! detail::point_on_surface::calculate_point_on_surface<1>(geometry, point, strategy))
{
// For invalid polygons, we might try X-direction
- detail::point_on_surface::calculate_point_on_surface<0>(geometry, point);
+ detail::point_on_surface::calculate_point_on_surface<0>(geometry, point, strategy);
}
}
/*!
+\brief Assigns a Point guaranteed to lie on the surface of the Geometry
+\tparam Geometry geometry type. This also defines the type of the output point
+\param geometry Geometry to take point from
+\param point Point to assign
+ */
+template <typename Geometry, typename Point>
+inline void point_on_surface(Geometry const& geometry, Point & point)
+{
+ typedef typename strategy::side::services::default_strategy
+ <
+ typename cs_tag<Geometry>::type
+ >::type strategy_type;
+
+ point_on_surface(geometry, point, strategy_type());
+}
+
+
+/*!
+\brief Returns point guaranteed to lie on the surface of the Geometry
+\tparam Geometry geometry type. This also defines the type of the output point
+\param geometry Geometry to take point from
+\param strategy side strategy
+\return The Point guaranteed to lie on the surface of the Geometry
+ */
+template<typename Geometry, typename SideStrategy>
+inline typename geometry::point_type<Geometry>::type
+return_point_on_surface(Geometry const& geometry, SideStrategy const& strategy)
+{
+ typename geometry::point_type<Geometry>::type result;
+ geometry::point_on_surface(geometry, result, strategy);
+ return result;
+}
+
+/*!
\brief Returns point guaranteed to lie on the surface of the Geometry
\tparam Geometry geometry type. This also defines the type of the output point
\param geometry Geometry to take point from
diff --git a/boost/geometry/algorithms/remove_spikes.hpp b/boost/geometry/algorithms/remove_spikes.hpp
index caa7fed9be..196b20c6a4 100644
--- a/boost/geometry/algorithms/remove_spikes.hpp
+++ b/boost/geometry/algorithms/remove_spikes.hpp
@@ -5,6 +5,11 @@
// Copyright (c) 2009-2013 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -34,6 +39,8 @@
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+
#include <boost/geometry/util/condition.hpp>
@@ -59,20 +66,13 @@ namespace detail { namespace remove_spikes
{
-template <typename Range>
struct range_remove_spikes
{
- typedef typename strategy::side::services::default_strategy
- <
- typename cs_tag<Range>::type
- >::type side_strategy;
-
- typedef typename coordinate_type<Range>::type coordinate_type;
- typedef typename point_type<Range>::type point_type;
-
-
- static inline void apply(Range& range)
+ template <typename Range, typename SideStrategy>
+ static inline void apply(Range& range, SideStrategy const& strategy)
{
+ typedef typename point_type<Range>::type point_type;
+
std::size_t n = boost::size(range);
std::size_t const min_num_points = core_detail::closure::minimum_ring_size
<
@@ -91,7 +91,10 @@ struct range_remove_spikes
cleaned.push_back(*it);
while(cleaned.size() >= 3
- && detail::point_is_spike_or_equal(cleaned.back(), *(cleaned.end() - 3), *(cleaned.end() - 2)))
+ && detail::point_is_spike_or_equal(cleaned.back(),
+ *(cleaned.end() - 3),
+ *(cleaned.end() - 2),
+ strategy))
{
// Remove pen-ultimate point causing the spike (or which was equal)
cleaned.erase(cleaned.end() - 2);
@@ -110,13 +113,21 @@ struct range_remove_spikes
found = false;
// Check for spike in first point
int const penultimate = 2;
- while(cleaned.size() >= 3 && detail::point_is_spike_or_equal(cleaned.front(), *(cleaned.end() - penultimate), cleaned.back()))
+ while(cleaned.size() >= 3
+ && detail::point_is_spike_or_equal(cleaned.front(),
+ *(cleaned.end() - penultimate),
+ cleaned.back(),
+ strategy))
{
cleaned.pop_back();
found = true;
}
// Check for spike in second point
- while(cleaned.size() >= 3 && detail::point_is_spike_or_equal(*(cleaned.begin() + 1), cleaned.back(), cleaned.front()))
+ while(cleaned.size() >= 3
+ && detail::point_is_spike_or_equal(*(cleaned.begin() + 1),
+ cleaned.back(),
+ cleaned.front(),
+ strategy))
{
cleaned.pop_front();
found = true;
@@ -144,15 +155,13 @@ struct range_remove_spikes
};
-template <typename Polygon>
struct polygon_remove_spikes
{
- static inline void apply(Polygon& polygon)
+ template <typename Polygon, typename SideStrategy>
+ static inline void apply(Polygon& polygon, SideStrategy const& strategy)
{
- typedef typename geometry::ring_type<Polygon>::type ring_type;
-
- typedef range_remove_spikes<ring_type> per_range;
- per_range::apply(exterior_ring(polygon));
+ typedef range_remove_spikes per_range;
+ per_range::apply(exterior_ring(polygon), strategy);
typename interior_return_type<Polygon>::type
rings = interior_rings(polygon);
@@ -160,23 +169,24 @@ struct polygon_remove_spikes
for (typename detail::interior_iterator<Polygon>::type
it = boost::begin(rings); it != boost::end(rings); ++it)
{
- per_range::apply(*it);
+ per_range::apply(*it, strategy);
}
}
};
-template <typename MultiGeometry, typename SingleVersion>
+template <typename SingleVersion>
struct multi_remove_spikes
{
- static inline void apply(MultiGeometry& multi)
+ template <typename MultiGeometry, typename SideStrategy>
+ static inline void apply(MultiGeometry& multi, SideStrategy const& strategy)
{
for (typename boost::range_iterator<MultiGeometry>::type
it = boost::begin(multi);
it != boost::end(multi);
++it)
{
- SingleVersion::apply(*it);
+ SingleVersion::apply(*it, strategy);
}
}
};
@@ -199,21 +209,22 @@ template
>
struct remove_spikes
{
- static inline void apply(Geometry&)
+ template <typename SideStrategy>
+ static inline void apply(Geometry&, SideStrategy const&)
{}
};
template <typename Ring>
struct remove_spikes<Ring, ring_tag>
- : detail::remove_spikes::range_remove_spikes<Ring>
+ : detail::remove_spikes::range_remove_spikes
{};
template <typename Polygon>
struct remove_spikes<Polygon, polygon_tag>
- : detail::remove_spikes::polygon_remove_spikes<Polygon>
+ : detail::remove_spikes::polygon_remove_spikes
{};
@@ -221,11 +232,7 @@ template <typename MultiPolygon>
struct remove_spikes<MultiPolygon, multi_polygon_tag>
: detail::remove_spikes::multi_remove_spikes
<
- MultiPolygon,
detail::remove_spikes::polygon_remove_spikes
- <
- typename boost::range_value<MultiPolygon>::type
- >
>
{};
@@ -239,28 +246,46 @@ namespace resolve_variant {
template <typename Geometry>
struct remove_spikes
{
- static void apply(Geometry& geometry)
+ template <typename Strategy>
+ static void apply(Geometry& geometry, Strategy const& strategy)
{
concepts::check<Geometry>();
- dispatch::remove_spikes<Geometry>::apply(geometry);
+ dispatch::remove_spikes<Geometry>::apply(geometry, strategy);
+ }
+
+ static void apply(Geometry& geometry, geometry::default_strategy const&)
+ {
+ typedef typename strategy::side::services::default_strategy
+ <
+ typename cs_tag<Geometry>::type
+ >::type side_strategy;
+
+ apply(geometry, side_strategy());
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct remove_spikes<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
+ template <typename Strategy>
struct visitor: boost::static_visitor<void>
{
+ Strategy const& m_strategy;
+
+ visitor(Strategy const& strategy) : m_strategy(strategy) {}
+
template <typename Geometry>
void operator()(Geometry& geometry) const
{
- remove_spikes<Geometry>::apply(geometry);
+ remove_spikes<Geometry>::apply(geometry, m_strategy);
}
};
- static inline void apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry)
+ template <typename Strategy>
+ static inline void apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry,
+ Strategy const& strategy)
{
- boost::apply_visitor(visitor(), geometry);
+ boost::apply_visitor(visitor<Strategy>(strategy), geometry);
}
};
@@ -275,7 +300,20 @@ struct remove_spikes<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
inline void remove_spikes(Geometry& geometry)
{
- resolve_variant::remove_spikes<Geometry>::apply(geometry);
+ resolve_variant::remove_spikes<Geometry>::apply(geometry, geometry::default_strategy());
+}
+
+/*!
+ \ingroup remove_spikes
+ \tparam Geometry geometry type
+ \tparam Strategy side strategy type
+ \param geometry the geometry to make remove_spikes
+ \param strategy the side strategy used by the algorithm
+*/
+template <typename Geometry, typename Strategy>
+inline void remove_spikes(Geometry& geometry, Strategy const& strategy)
+{
+ resolve_variant::remove_spikes<Geometry>::apply(geometry, strategy);
}
diff --git a/boost/geometry/algorithms/touches.hpp b/boost/geometry/algorithms/touches.hpp
index 49e104d258..d358c3f20e 100644
--- a/boost/geometry/algorithms/touches.hpp
+++ b/boost/geometry/algorithms/touches.hpp
@@ -21,687 +21,8 @@
#define BOOST_GEOMETRY_ALGORITHMS_TOUCHES_HPP
-#include <deque>
+#include <boost/geometry/algorithms/detail/touches/interface.hpp>
+#include <boost/geometry/algorithms/detail/touches/implementation.hpp>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
-#include <boost/geometry/geometries/concepts/check.hpp>
-#include <boost/geometry/algorithms/detail/for_each_range.hpp>
-#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
-#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
-#include <boost/geometry/algorithms/disjoint.hpp>
-#include <boost/geometry/algorithms/intersects.hpp>
-#include <boost/geometry/algorithms/num_geometries.hpp>
-#include <boost/geometry/algorithms/detail/sub_range.hpp>
-#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
-
-#include <boost/geometry/algorithms/relate.hpp>
-#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
-
-
-namespace boost { namespace geometry
-{
-
-#ifndef DOXYGEN_NO_DETAIL
-namespace detail { namespace touches
-{
-
-// Box/Box
-
-template
-<
- std::size_t Dimension,
- std::size_t DimensionCount
->
-struct box_box_loop
-{
- template <typename Box1, typename Box2>
- static inline bool apply(Box1 const& b1, Box2 const& b2, bool & touch)
- {
- typedef typename coordinate_type<Box1>::type coordinate_type1;
- typedef typename coordinate_type<Box2>::type coordinate_type2;
-
- coordinate_type1 const& min1 = get<min_corner, Dimension>(b1);
- coordinate_type1 const& max1 = get<max_corner, Dimension>(b1);
- coordinate_type2 const& min2 = get<min_corner, Dimension>(b2);
- coordinate_type2 const& max2 = get<max_corner, Dimension>(b2);
-
- // TODO assert or exception?
- //BOOST_GEOMETRY_ASSERT(min1 <= max1 && min2 <= max2);
-
- if (max1 < min2 || max2 < min1)
- {
- return false;
- }
-
- if (max1 == min2 || max2 == min1)
- {
- touch = true;
- }
-
- return box_box_loop
- <
- Dimension + 1,
- DimensionCount
- >::apply(b1, b2, touch);
- }
-};
-
-template
-<
- std::size_t DimensionCount
->
-struct box_box_loop<DimensionCount, DimensionCount>
-{
- template <typename Box1, typename Box2>
- static inline bool apply(Box1 const& , Box2 const&, bool &)
- {
- return true;
- }
-};
-
-struct box_box
-{
- template <typename Box1, typename Box2, typename Strategy>
- static inline bool apply(Box1 const& b1, Box2 const& b2, Strategy const& /*strategy*/)
- {
- BOOST_STATIC_ASSERT((boost::is_same
- <
- typename geometry::coordinate_system<Box1>::type,
- typename geometry::coordinate_system<Box2>::type
- >::value
- ));
- assert_dimension_equal<Box1, Box2>();
-
- bool touches = false;
- bool ok = box_box_loop
- <
- 0,
- dimension<Box1>::type::value
- >::apply(b1, b2, touches);
-
- return ok && touches;
- }
-};
-
-// Areal/Areal
-
-struct areal_interrupt_policy
-{
- static bool const enabled = true;
- bool found_touch;
- bool found_not_touch;
-
- // dummy variable required by self_get_turn_points::get_turns
- static bool const has_intersections = false;
-
- inline bool result()
- {
- return found_touch && !found_not_touch;
- }
-
- inline areal_interrupt_policy()
- : found_touch(false), found_not_touch(false)
- {}
-
- template <typename Range>
- inline bool apply(Range const& range)
- {
- // if already rejected (temp workaround?)
- if ( found_not_touch )
- return true;
-
- typedef typename boost::range_iterator<Range const>::type iterator;
- for ( iterator it = boost::begin(range) ; it != boost::end(range) ; ++it )
- {
- if ( it->has(overlay::operation_intersection) )
- {
- found_not_touch = true;
- return true;
- }
-
- switch(it->method)
- {
- case overlay::method_crosses:
- found_not_touch = true;
- return true;
- case overlay::method_equal:
- // Segment spatially equal means: at the right side
- // the polygon internally overlaps. So return false.
- found_not_touch = true;
- return true;
- case overlay::method_touch:
- case overlay::method_touch_interior:
- case overlay::method_collinear:
- if ( ok_for_touch(*it) )
- {
- found_touch = true;
- }
- else
- {
- found_not_touch = true;
- return true;
- }
- break;
- case overlay::method_none :
- case overlay::method_disjoint :
- case overlay::method_error :
- break;
- }
- }
-
- return false;
- }
-
- template <typename Turn>
- inline bool ok_for_touch(Turn const& turn)
- {
- return turn.both(overlay::operation_union)
- || turn.both(overlay::operation_blocked)
- || turn.combination(overlay::operation_union, overlay::operation_blocked)
- ;
- }
-};
-
-template<typename Geometry, typename PointInRingStrategy>
-struct check_each_ring_for_within
-{
- bool has_within;
- Geometry const& m_geometry;
- PointInRingStrategy const& m_strategy;
-
- inline check_each_ring_for_within(Geometry const& g, PointInRingStrategy const& strategy)
- : has_within(false)
- , m_geometry(g)
- , m_strategy(strategy)
- {}
-
- template <typename Range>
- inline void apply(Range const& range)
- {
- typename geometry::point_type<Range>::type p;
- geometry::point_on_border(p, range);
- if ( !has_within && geometry::within(p, m_geometry, m_strategy) )
- {
- has_within = true;
- }
- }
-};
-
-template <typename FirstGeometry, typename SecondGeometry, typename IntersectionStrategy>
-inline bool rings_containing(FirstGeometry const& geometry1,
- SecondGeometry const& geometry2,
- IntersectionStrategy const& strategy)
-{
- // NOTE: This strategy could be defined inside IntersectionStrategy
- typedef typename IntersectionStrategy::template point_in_geometry_strategy
- <
- FirstGeometry, SecondGeometry
- >::type point_in_ring_strategy_type;
-
- point_in_ring_strategy_type point_in_ring_strategy
- = strategy.template get_point_in_geometry_strategy<FirstGeometry, SecondGeometry>();
-
- check_each_ring_for_within
- <
- FirstGeometry, point_in_ring_strategy_type
- > checker(geometry1, point_in_ring_strategy);
- geometry::detail::for_each_range(geometry2, checker);
- return checker.has_within;
-}
-
-template <typename Geometry1, typename Geometry2>
-struct areal_areal
-{
- template <typename IntersectionStrategy>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- IntersectionStrategy const& strategy)
- {
- typedef detail::no_rescale_policy rescale_policy_type;
- typedef typename geometry::point_type<Geometry1>::type point_type;
- typedef detail::overlay::turn_info
- <
- point_type,
- typename segment_ratio_type<point_type, rescale_policy_type>::type
- > turn_info;
-
- std::deque<turn_info> turns;
- detail::touches::areal_interrupt_policy policy;
- rescale_policy_type robust_policy;
- boost::geometry::get_turns
- <
- detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
- detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
- detail::overlay::assign_null_policy
- >(geometry1, geometry2, strategy, robust_policy, turns, policy);
-
- return policy.result()
- && ! geometry::detail::touches::rings_containing(geometry1, geometry2, strategy)
- && ! geometry::detail::touches::rings_containing(geometry2, geometry1, strategy);
- }
-};
-
-// P/*
-
-struct use_point_in_geometry
-{
- template <typename Point, typename Geometry, typename Strategy>
- static inline bool apply(Point const& point, Geometry const& geometry, Strategy const& strategy)
- {
- return detail::within::point_in_geometry(point, geometry, strategy) == 0;
- }
-};
-
-}}
-#endif // DOXYGEN_NO_DETAIL
-
-#ifndef DOXYGEN_NO_DISPATCH
-namespace dispatch {
-
-// TODO: Since CastedTags are used is Reverse needed?
-
-template
-<
- typename Geometry1,
- typename Geometry2,
- typename Tag1 = typename tag<Geometry1>::type,
- typename Tag2 = typename tag<Geometry2>::type,
- typename CastedTag1 = typename tag_cast<Tag1, pointlike_tag, linear_tag, areal_tag>::type,
- typename CastedTag2 = typename tag_cast<Tag2, pointlike_tag, linear_tag, areal_tag>::type,
- bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
->
-struct touches
- : not_implemented<Tag1, Tag2>
-{};
-
-// If reversal is needed, perform it
-template
-<
- typename Geometry1, typename Geometry2,
- typename Tag1, typename Tag2,
- typename CastedTag1, typename CastedTag2
->
-struct touches<Geometry1, Geometry2, Tag1, Tag2, CastedTag1, CastedTag2, true>
- : touches<Geometry2, Geometry1, Tag2, Tag1, CastedTag2, CastedTag1, false>
-{
- template <typename Strategy>
- static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
- {
- return touches<Geometry2, Geometry1>::apply(g2, g1, strategy);
- }
-};
-
-// P/P
-
-template <typename Geometry1, typename Geometry2, typename Tag2>
-struct touches<Geometry1, Geometry2, point_tag, Tag2, pointlike_tag, pointlike_tag, false>
-{
- template <typename Strategy>
- static inline bool apply(Geometry1 const& , Geometry2 const& , Strategy const&)
- {
- return false;
- }
-};
-
-template <typename Geometry1, typename Geometry2, typename Tag2>
-struct touches<Geometry1, Geometry2, multi_point_tag, Tag2, pointlike_tag, pointlike_tag, false>
-{
- template <typename Strategy>
- static inline bool apply(Geometry1 const&, Geometry2 const&, Strategy const&)
- {
- return false;
- }
-};
-
-// P/*
-
-template <typename Point, typename Geometry, typename Tag2, typename CastedTag2>
-struct touches<Point, Geometry, point_tag, Tag2, pointlike_tag, CastedTag2, false>
- : detail::touches::use_point_in_geometry
-{};
-
-// TODO: support touches(MPt, Linear/Areal)
-
-// Box/Box
-
-template <typename Box1, typename Box2, typename CastedTag1, typename CastedTag2>
-struct touches<Box1, Box2, box_tag, box_tag, CastedTag1, CastedTag2, false>
- : detail::touches::box_box
-{};
-
-template <typename Box1, typename Box2>
-struct touches<Box1, Box2, box_tag, box_tag, areal_tag, areal_tag, false>
- : detail::touches::box_box
-{};
-
-// L/L
-
-template <typename Linear1, typename Linear2, typename Tag1, typename Tag2>
-struct touches<Linear1, Linear2, Tag1, Tag2, linear_tag, linear_tag, false>
- : detail::relate::relate_impl
- <
- detail::de9im::static_mask_touches_type,
- Linear1,
- Linear2
- >
-{};
-
-// L/A
-
-template <typename Linear, typename Areal, typename Tag1, typename Tag2>
-struct touches<Linear, Areal, Tag1, Tag2, linear_tag, areal_tag, false>
- : detail::relate::relate_impl
- <
- detail::de9im::static_mask_touches_type,
- Linear,
- Areal
- >
-{};
-
-// A/L
-template <typename Linear, typename Areal, typename Tag1, typename Tag2>
-struct touches<Areal, Linear, Tag1, Tag2, areal_tag, linear_tag, false>
- : detail::relate::relate_impl
- <
- detail::de9im::static_mask_touches_type,
- Areal,
- Linear
- >
-{};
-
-// A/A
-
-template <typename Areal1, typename Areal2, typename Tag1, typename Tag2>
-struct touches<Areal1, Areal2, Tag1, Tag2, areal_tag, areal_tag, false>
- : detail::relate::relate_impl
- <
- detail::de9im::static_mask_touches_type,
- Areal1,
- Areal2
- >
-{};
-
-template <typename Areal1, typename Areal2>
-struct touches<Areal1, Areal2, ring_tag, ring_tag, areal_tag, areal_tag, false>
- : detail::touches::areal_areal<Areal1, Areal2>
-{};
-
-} // namespace dispatch
-#endif // DOXYGEN_NO_DISPATCH
-
-
-namespace resolve_strategy
-{
-
-struct touches
-{
- template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- return dispatch::touches
- <
- Geometry1, Geometry2
- >::apply(geometry1, geometry2, strategy);
- }
-
- template <typename Geometry1, typename Geometry2>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- default_strategy)
- {
- typedef typename strategy::relate::services::default_strategy
- <
- Geometry1,
- Geometry2
- >::type strategy_type;
-
- return dispatch::touches
- <
- Geometry1, Geometry2
- >::apply(geometry1, geometry2, strategy_type());
- }
-};
-
-} // namespace resolve_strategy
-
-
-namespace resolve_variant {
-
-template <typename Geometry1, typename Geometry2>
-struct touches
-{
- template <typename Strategy>
- static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
- {
- concepts::check<Geometry1 const>();
- concepts::check<Geometry2 const>();
-
- return resolve_strategy::touches::apply(geometry1, geometry2, strategy);
- }
-};
-
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
-{
- template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
- {
- Geometry2 const& m_geometry2;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2, Strategy const& strategy)
- : m_geometry2(geometry2)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry1>
- bool operator()(Geometry1 const& geometry1) const
- {
- return touches<Geometry1, Geometry2>::apply(geometry1, m_geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
- }
-};
-
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct touches<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
-{
- template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
- {
- Geometry1 const& m_geometry1;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1, Strategy const& strategy)
- : m_geometry1(geometry1)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry2>
- bool operator()(Geometry2 const& geometry2) const
- {
- return touches<Geometry1, Geometry2>::apply(m_geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
- }
-};
-
-template <BOOST_VARIANT_ENUM_PARAMS(typename T1),
- BOOST_VARIANT_ENUM_PARAMS(typename T2)>
-struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
-{
- template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
- {
- Strategy const& m_strategy;
-
- visitor(Strategy const& strategy)
- : m_strategy(strategy)
- {}
-
- template <typename Geometry1, typename Geometry2>
- bool operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
- {
- return touches<Geometry1, Geometry2>::apply(geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
- }
-};
-
-template <typename Geometry>
-struct self_touches
-{
- static bool apply(Geometry const& geometry)
- {
- concepts::check<Geometry const>();
-
- typedef typename strategy::relate::services::default_strategy
- <
- Geometry, Geometry
- >::type strategy_type;
- typedef detail::no_rescale_policy rescale_policy_type;
- typedef typename geometry::point_type<Geometry>::type point_type;
- typedef detail::overlay::turn_info
- <
- point_type,
- typename segment_ratio_type<point_type, rescale_policy_type>::type
- > turn_info;
-
- typedef detail::overlay::get_turn_info
- <
- detail::overlay::assign_null_policy
- > policy_type;
-
- std::deque<turn_info> turns;
- detail::touches::areal_interrupt_policy policy;
- strategy_type strategy;
- rescale_policy_type robust_policy;
- detail::self_get_turn_points::get_turns
- <
- policy_type
- >::apply(geometry, strategy, robust_policy, turns, policy);
-
- return policy.result();
- }
-};
-
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct self_touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
-{
- struct visitor: boost::static_visitor<bool>
- {
- template <typename Geometry>
- bool operator()(Geometry const& geometry) const
- {
- return self_touches<Geometry>::apply(geometry);
- }
- };
-
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
- {
- return boost::apply_visitor(visitor(), geometry);
- }
-};
-
-} // namespace resolve_variant
-
-
-/*!
-\brief \brief_check{has at least one touching point (self-tangency)}
-\note This function can be called for one geometry (self-tangency) and
- also for two geometries (touch)
-\ingroup touches
-\tparam Geometry \tparam_geometry
-\param geometry \param_geometry
-\return \return_check{is self-touching}
-
-\qbk{distinguish,one geometry}
-\qbk{[def __one_parameter__]}
-\qbk{[include reference/algorithms/touches.qbk]}
-*/
-template <typename Geometry>
-inline bool touches(Geometry const& geometry)
-{
- return resolve_variant::self_touches<Geometry>::apply(geometry);
-}
-
-
-/*!
-\brief \brief_check2{have at least one touching point (tangent - non overlapping)}
-\ingroup touches
-\tparam Geometry1 \tparam_geometry
-\tparam Geometry2 \tparam_geometry
-\param geometry1 \param_geometry
-\param geometry2 \param_geometry
-\return \return_check2{touch each other}
-
-\qbk{distinguish,two geometries}
-\qbk{[include reference/algorithms/touches.qbk]}
- */
-template <typename Geometry1, typename Geometry2>
-inline bool touches(Geometry1 const& geometry1, Geometry2 const& geometry2)
-{
- return resolve_variant::touches
- <
- Geometry1, Geometry2
- >::apply(geometry1, geometry2, default_strategy());
-}
-
-/*!
-\brief \brief_check2{have at least one touching point (tangent - non overlapping)}
-\ingroup touches
-\tparam Geometry1 \tparam_geometry
-\tparam Geometry2 \tparam_geometry
-\tparam Strategy \tparam_strategy{Touches}
-\param geometry1 \param_geometry
-\param geometry2 \param_geometry
-\param strategy \param_strategy{touches}
-\return \return_check2{touch each other}
-
-\qbk{distinguish,with strategy}
-\qbk{[include reference/algorithms/touches.qbk]}
- */
-template <typename Geometry1, typename Geometry2, typename Strategy>
-inline bool touches(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
-{
- return resolve_variant::touches
- <
- Geometry1, Geometry2
- >::apply(geometry1, geometry2, strategy);
-}
-
-
-}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_TOUCHES_HPP
diff --git a/boost/geometry/algorithms/within.hpp b/boost/geometry/algorithms/within.hpp
index ba170dd27b..e657bbda24 100644
--- a/boost/geometry/algorithms/within.hpp
+++ b/boost/geometry/algorithms/within.hpp
@@ -20,504 +20,8 @@
#define BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP
-#include <cstddef>
+#include <boost/geometry/algorithms/detail/within/interface.hpp>
+#include <boost/geometry/algorithms/detail/within/implementation.hpp>
-#include <boost/concept_check.hpp>
-#include <boost/range.hpp>
-
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
-#include <boost/geometry/algorithms/make.hpp>
-#include <boost/geometry/algorithms/not_implemented.hpp>
-
-#include <boost/geometry/core/access.hpp>
-#include <boost/geometry/core/closure.hpp>
-#include <boost/geometry/core/cs.hpp>
-#include <boost/geometry/core/exterior_ring.hpp>
-#include <boost/geometry/core/interior_rings.hpp>
-#include <boost/geometry/core/point_order.hpp>
-#include <boost/geometry/core/ring_type.hpp>
-#include <boost/geometry/core/interior_rings.hpp>
-#include <boost/geometry/core/tags.hpp>
-
-#include <boost/geometry/geometries/concepts/check.hpp>
-#include <boost/geometry/strategies/concepts/within_concept.hpp>
-#include <boost/geometry/strategies/default_strategy.hpp>
-#include <boost/geometry/strategies/within.hpp>
-#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/order_as_direction.hpp>
-#include <boost/geometry/views/closeable_view.hpp>
-#include <boost/geometry/views/reversible_view.hpp>
-
-#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
-#include <boost/geometry/algorithms/relate.hpp>
-
-#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
-#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
-#include <deque>
-
-namespace boost { namespace geometry
-{
-
-#ifndef DOXYGEN_NO_DETAIL
-namespace detail { namespace within {
-
-struct use_point_in_geometry
-{
- template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
- {
- return detail::within::point_in_geometry(geometry1, geometry2, strategy) == 1;
- }
-};
-
-struct use_relate
-{
- template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
- {
- typedef typename detail::de9im::static_mask_within_type
- <
- Geometry1, Geometry2
- >::type within_mask;
- return geometry::relate(geometry1, geometry2, within_mask(), strategy);
- }
-};
-
-}} // namespace detail::within
-#endif // DOXYGEN_NO_DETAIL
-
-#ifndef DOXYGEN_NO_DISPATCH
-namespace dispatch
-{
-
-template
-<
- typename Geometry1,
- typename Geometry2,
- typename Tag1 = typename tag<Geometry1>::type,
- typename Tag2 = typename tag<Geometry2>::type
->
-struct within
- : not_implemented<Tag1, Tag2>
-{};
-
-
-template <typename Point, typename Box>
-struct within<Point, Box, point_tag, box_tag>
-{
- template <typename Strategy>
- static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
- {
- boost::ignore_unused_variable_warning(strategy);
- return strategy.apply(point, box);
- }
-};
-
-template <typename Box1, typename Box2>
-struct within<Box1, Box2, box_tag, box_tag>
-{
- template <typename Strategy>
- static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
- {
- assert_dimension_equal<Box1, Box2>();
- boost::ignore_unused_variable_warning(strategy);
- return strategy.apply(box1, box2);
- }
-};
-
-// P/P
-
-template <typename Point1, typename Point2>
-struct within<Point1, Point2, point_tag, point_tag>
- : public detail::within::use_point_in_geometry
-{};
-
-template <typename Point, typename MultiPoint>
-struct within<Point, MultiPoint, point_tag, multi_point_tag>
- : public detail::within::use_point_in_geometry
-{};
-
-// P/L
-
-template <typename Point, typename Segment>
-struct within<Point, Segment, point_tag, segment_tag>
- : public detail::within::use_point_in_geometry
-{};
-
-template <typename Point, typename Linestring>
-struct within<Point, Linestring, point_tag, linestring_tag>
- : public detail::within::use_point_in_geometry
-{};
-
-template <typename Point, typename MultiLinestring>
-struct within<Point, MultiLinestring, point_tag, multi_linestring_tag>
- : public detail::within::use_point_in_geometry
-{};
-
-// P/A
-
-template <typename Point, typename Ring>
-struct within<Point, Ring, point_tag, ring_tag>
- : public detail::within::use_point_in_geometry
-{};
-
-template <typename Point, typename Polygon>
-struct within<Point, Polygon, point_tag, polygon_tag>
- : public detail::within::use_point_in_geometry
-{};
-
-template <typename Point, typename MultiPolygon>
-struct within<Point, MultiPolygon, point_tag, multi_polygon_tag>
- : public detail::within::use_point_in_geometry
-{};
-
-// L/L
-
-template <typename Linestring1, typename Linestring2>
-struct within<Linestring1, Linestring2, linestring_tag, linestring_tag>
- : public detail::within::use_relate
-{};
-
-template <typename Linestring, typename MultiLinestring>
-struct within<Linestring, MultiLinestring, linestring_tag, multi_linestring_tag>
- : public detail::within::use_relate
-{};
-
-template <typename MultiLinestring, typename Linestring>
-struct within<MultiLinestring, Linestring, multi_linestring_tag, linestring_tag>
- : public detail::within::use_relate
-{};
-
-template <typename MultiLinestring1, typename MultiLinestring2>
-struct within<MultiLinestring1, MultiLinestring2, multi_linestring_tag, multi_linestring_tag>
- : public detail::within::use_relate
-{};
-
-// L/A
-
-template <typename Linestring, typename Ring>
-struct within<Linestring, Ring, linestring_tag, ring_tag>
- : public detail::within::use_relate
-{};
-
-template <typename MultiLinestring, typename Ring>
-struct within<MultiLinestring, Ring, multi_linestring_tag, ring_tag>
- : public detail::within::use_relate
-{};
-
-template <typename Linestring, typename Polygon>
-struct within<Linestring, Polygon, linestring_tag, polygon_tag>
- : public detail::within::use_relate
-{};
-
-template <typename MultiLinestring, typename Polygon>
-struct within<MultiLinestring, Polygon, multi_linestring_tag, polygon_tag>
- : public detail::within::use_relate
-{};
-
-template <typename Linestring, typename MultiPolygon>
-struct within<Linestring, MultiPolygon, linestring_tag, multi_polygon_tag>
- : public detail::within::use_relate
-{};
-
-template <typename MultiLinestring, typename MultiPolygon>
-struct within<MultiLinestring, MultiPolygon, multi_linestring_tag, multi_polygon_tag>
- : public detail::within::use_relate
-{};
-
-// A/A
-
-template <typename Ring1, typename Ring2>
-struct within<Ring1, Ring2, ring_tag, ring_tag>
- : public detail::within::use_relate
-{};
-
-template <typename Ring, typename Polygon>
-struct within<Ring, Polygon, ring_tag, polygon_tag>
- : public detail::within::use_relate
-{};
-
-template <typename Polygon, typename Ring>
-struct within<Polygon, Ring, polygon_tag, ring_tag>
- : public detail::within::use_relate
-{};
-
-template <typename Polygon1, typename Polygon2>
-struct within<Polygon1, Polygon2, polygon_tag, polygon_tag>
- : public detail::within::use_relate
-{};
-
-template <typename Ring, typename MultiPolygon>
-struct within<Ring, MultiPolygon, ring_tag, multi_polygon_tag>
- : public detail::within::use_relate
-{};
-
-template <typename MultiPolygon, typename Ring>
-struct within<MultiPolygon, Ring, multi_polygon_tag, ring_tag>
- : public detail::within::use_relate
-{};
-
-template <typename Polygon, typename MultiPolygon>
-struct within<Polygon, MultiPolygon, polygon_tag, multi_polygon_tag>
- : public detail::within::use_relate
-{};
-
-template <typename MultiPolygon, typename Polygon>
-struct within<MultiPolygon, Polygon, multi_polygon_tag, polygon_tag>
- : public detail::within::use_relate
-{};
-
-template <typename MultiPolygon1, typename MultiPolygon2>
-struct within<MultiPolygon1, MultiPolygon2, multi_polygon_tag, multi_polygon_tag>
- : public detail::within::use_relate
-{};
-
-} // namespace dispatch
-#endif // DOXYGEN_NO_DISPATCH
-
-
-namespace resolve_strategy
-{
-
-struct within
-{
- template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- concepts::within::check
- <
- typename tag<Geometry1>::type,
- typename tag<Geometry2>::type,
- typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
- Strategy
- >();
-
- return dispatch::within<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
- }
-
- template <typename Geometry1, typename Geometry2>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- default_strategy)
- {
- typedef typename strategy::within::services::default_strategy
- <
- Geometry1,
- Geometry2
- >::type strategy_type;
-
- return apply(geometry1, geometry2, strategy_type());
- }
-};
-
-} // namespace resolve_strategy
-
-
-namespace resolve_variant
-{
-
-template <typename Geometry1, typename Geometry2>
-struct within
-{
- template <typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- concepts::check<Geometry1 const>();
- concepts::check<Geometry2 const>();
- assert_dimension_equal<Geometry1, Geometry2>();
-
- return resolve_strategy::within::apply(geometry1,
- geometry2,
- strategy);
- }
-};
-
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct within<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
-{
- template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
- {
- Geometry2 const& m_geometry2;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2, Strategy const& strategy)
- : m_geometry2(geometry2)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry1>
- bool operator()(Geometry1 const& geometry1) const
- {
- return within<Geometry1, Geometry2>::apply(geometry1,
- m_geometry2,
- m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry2, strategy),
- geometry1);
- }
-};
-
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct within<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
-{
- template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
- {
- Geometry1 const& m_geometry1;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1, Strategy const& strategy)
- : m_geometry1(geometry1)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry2>
- bool operator()(Geometry2 const& geometry2) const
- {
- return within<Geometry1, Geometry2>::apply(m_geometry1,
- geometry2,
- m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool
- apply(Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry1, strategy),
- geometry2
- );
- }
-};
-
-template <
- BOOST_VARIANT_ENUM_PARAMS(typename T1),
- BOOST_VARIANT_ENUM_PARAMS(typename T2)
->
-struct within<
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
->
-{
- template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
- {
- Strategy const& m_strategy;
-
- visitor(Strategy const& strategy): m_strategy(strategy) {}
-
- template <typename Geometry1, typename Geometry2>
- bool operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
- {
- return within<Geometry1, Geometry2>::apply(geometry1,
- geometry2,
- m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(strategy),
- geometry1,
- geometry2);
- }
-};
-
-}
-
-
-/*!
-\brief \brief_check12{is completely inside}
-\ingroup within
-\details \details_check12{within, is completely inside}.
-\tparam Geometry1 \tparam_geometry
-\tparam Geometry2 \tparam_geometry
-\param geometry1 \param_geometry which might be within the second geometry
-\param geometry2 \param_geometry which might contain the first geometry
-\return true if geometry1 is completely contained within geometry2,
- else false
-\note The default strategy is used for within detection
-
-
-\qbk{[include reference/algorithms/within.qbk]}
-
-\qbk{
-[heading Example]
-[within]
-[within_output]
-}
- */
-template<typename Geometry1, typename Geometry2>
-inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2)
-{
- return resolve_variant::within
- <
- Geometry1,
- Geometry2
- >::apply(geometry1, geometry2, default_strategy());
-}
-
-/*!
-\brief \brief_check12{is completely inside} \brief_strategy
-\ingroup within
-\details \details_check12{within, is completely inside}, \brief_strategy. \details_strategy_reasons
-\tparam Geometry1 \tparam_geometry
-\tparam Geometry2 \tparam_geometry
-\param geometry1 \param_geometry which might be within the second geometry
-\param geometry2 \param_geometry which might contain the first geometry
-\param strategy strategy to be used
-\return true if geometry1 is completely contained within geometry2,
- else false
-
-\qbk{distinguish,with strategy}
-\qbk{[include reference/algorithms/within.qbk]}
-\qbk{
-[heading Available Strategies]
-\* [link geometry.reference.strategies.strategy_within_winding Winding (coordinate system agnostic)]
-\* [link geometry.reference.strategies.strategy_within_franklin Franklin (cartesian)]
-\* [link geometry.reference.strategies.strategy_within_crossings_multiply Crossings Multiply (cartesian)]
-
-[heading Example]
-[within_strategy]
-[within_strategy_output]
-
-}
-*/
-template<typename Geometry1, typename Geometry2, typename Strategy>
-inline bool within(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
-{
- return resolve_variant::within
- <
- Geometry1,
- Geometry2
- >::apply(geometry1, geometry2, strategy);
-}
-
-}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP
diff --git a/boost/geometry/core/radian_access.hpp b/boost/geometry/core/radian_access.hpp
index 374c2954a2..993a6cc4c4 100644
--- a/boost/geometry/core/radian_access.hpp
+++ b/boost/geometry/core/radian_access.hpp
@@ -107,6 +107,72 @@ struct radian_access<1, Geometry, CoordinateSystem<degree> >
{};
+template<std::size_t Index, std::size_t Dimension, typename Geometry>
+struct degree_radian_converter_box_segment
+{
+ typedef typename fp_coordinate_type<Geometry>::type coordinate_type;
+
+ static inline coordinate_type get(Geometry const& geometry)
+ {
+ return boost::numeric_cast
+ <
+ coordinate_type
+ >(geometry::get<Index, Dimension>(geometry)
+ * math::d2r<coordinate_type>());
+ }
+
+ static inline void set(Geometry& geometry, coordinate_type const& radians)
+ {
+ geometry::set<Index, Dimension>(geometry, boost::numeric_cast
+ <
+ coordinate_type
+ >(radians * math::r2d<coordinate_type>()));
+ }
+
+};
+
+
+// Default, radian (or any other coordinate system) just works like "get"
+template <std::size_t Index, std::size_t Dimension, typename Geometry, typename DegreeOrRadian>
+struct radian_access_box_segment
+{
+ typedef typename fp_coordinate_type<Geometry>::type coordinate_type;
+
+ static inline coordinate_type get(Geometry const& geometry)
+ {
+ return geometry::get<Index, Dimension>(geometry);
+ }
+
+ static inline void set(Geometry& geometry, coordinate_type const& radians)
+ {
+ geometry::set<Index, Dimension>(geometry, radians);
+ }
+};
+
+// Specialize, any "degree" coordinate system will be converted to radian
+// but only for dimension 0,1 (so: dimension 2 and heigher are untouched)
+
+template
+<
+ typename Geometry,
+ template<typename> class CoordinateSystem,
+ std::size_t Index
+>
+struct radian_access_box_segment<Index, 0, Geometry, CoordinateSystem<degree> >
+ : degree_radian_converter_box_segment<Index, 0, Geometry>
+{};
+
+
+template
+<
+ typename Geometry,
+ template<typename> class CoordinateSystem,
+ std::size_t Index
+>
+struct radian_access_box_segment<Index, 1, Geometry, CoordinateSystem<degree> >
+ : degree_radian_converter_box_segment<Index, 1, Geometry>
+{};
+
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
@@ -130,7 +196,6 @@ inline typename fp_coordinate_type<Geometry>::type get_as_radian(Geometry const&
typename coordinate_system<Geometry>::type>::get(geometry);
}
-
/*!
\brief set coordinate value (in radian) to a point
\details Coordinate value will be set correctly, if coordinate system of
@@ -151,6 +216,46 @@ inline void set_from_radian(Geometry& geometry,
typename coordinate_system<Geometry>::type>::set(geometry, radians);
}
+/*!
+\brief get coordinate value of a segment or box, result is in Radian
+\details Result is in Radian, even if source coordinate system
+ is in Degrees
+\return coordinate value
+\ingroup get
+\tparam Index index
+\tparam Dimension dimension
+\tparam Geometry geometry
+\param geometry geometry to get coordinate value from
+\note Only applicable to coordinate systems templatized by units,
+ e.g. spherical or geographic coordinate systems
+*/
+template <std::size_t Index, std::size_t Dimension, typename Geometry>
+inline typename fp_coordinate_type<Geometry>::type get_as_radian(Geometry const& geometry)
+{
+ return detail::radian_access_box_segment<Index, Dimension, Geometry,
+ typename coordinate_system<Geometry>::type>::get(geometry);
+}
+
+/*!
+\brief set coordinate value (in radian) to a segment or box
+\details Coordinate value will be set correctly, if coordinate system of
+ point is in Degree, Radian value will be converted to Degree
+\ingroup set
+\tparam Index index
+\tparam Dimension dimension
+\tparam Geometry geometry
+\param geometry geometry to assign coordinate to
+\param radians coordinate value to assign
+\note Only applicable to coordinate systems templatized by units,
+ e.g. spherical or geographic coordinate systems
+*/
+template <std::size_t Index, std::size_t Dimension, typename Geometry>
+inline void set_from_radian(Geometry& geometry,
+ typename fp_coordinate_type<Geometry>::type const& radians)
+{
+ detail::radian_access_box_segment<Index, Dimension, Geometry,
+ typename coordinate_system<Geometry>::type>::set(geometry, radians);
+}
}} // namespace boost::geometry
diff --git a/boost/geometry/formulas/vertex_longitude.hpp b/boost/geometry/formulas/vertex_longitude.hpp
new file mode 100644
index 0000000000..00f2fd4e7a
--- /dev/null
+++ b/boost/geometry/formulas/vertex_longitude.hpp
@@ -0,0 +1,339 @@
+// Boost.Geometry
+
+// Copyright (c) 2016-2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the 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_GEOMETRY_FORMULAS_MAXIMUM_LONGITUDE_HPP
+#define BOOST_GEOMETRY_FORMULAS_MAXIMUM_LONGITUDE_HPP
+
+#include <boost/geometry/formulas/spherical.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
+#include <boost/geometry/core/srs.hpp>
+#include <boost/mpl/assert.hpp>
+
+#include <boost/math/special_functions/hypot.hpp>
+
+namespace boost { namespace geometry { namespace formula
+{
+
+/*!
+\brief Algorithm to compute the vertex longitude of a geodesic segment. Vertex is
+a point on the geodesic that maximizes (or minimizes) the latitude. The algorithm
+is given the vertex latitude.
+*/
+
+//Classes for spesific CS
+
+template <typename CT>
+class vertex_longitude_on_sphere
+{
+
+public:
+
+ template <typename T>
+ static inline CT apply(T const& lat1, //segment point 1
+ T const& lat2, //segment point 2
+ T const& lat3, //vertex latitude
+ T const& sin_l12,
+ T const& cos_l12) //lon1 -lon2
+ {
+ //https://en.wikipedia.org/wiki/Great-circle_navigation#Finding_way-points
+ CT const A = sin(lat1) * cos(lat2) * cos(lat3) * sin_l12;
+ CT const B = sin(lat1) * cos(lat2) * cos(lat3) * cos_l12
+ - cos(lat1) * sin(lat2) * cos(lat3);
+ CT lon = atan2(B, A);
+ return lon + math::pi<CT>();
+ }
+};
+
+template <typename CT>
+class vertex_longitude_on_spheroid
+{
+ template<typename T>
+ static inline void normalize(T& x, T& y)
+ {
+ T h = boost::math::hypot(x, y);
+ x /= h;
+ y /= h;
+ }
+
+public:
+
+ template <typename T, typename Spheroid>
+ static inline CT apply(T const& lat1, //segment point 1
+ T const& lat2, //segment point 2
+ T const& lat3, //vertex latitude
+ T& alp1,
+ Spheroid const& spheroid)
+ {
+ // We assume that segment points lay on different side w.r.t.
+ // the vertex
+
+ // Constants
+ CT const c0 = 0;
+ CT const c2 = 2;
+ CT const half_pi = math::pi<CT>() / c2;
+ if (math::equals(lat1, half_pi)
+ || math::equals(lat2, half_pi)
+ || math::equals(lat1, -half_pi)
+ || math::equals(lat2, -half_pi))
+ {
+ // one segment point is the pole
+ return c0;
+ }
+
+ // More constants
+ CT const f = flattening<CT>(spheroid);
+ CT const pi = math::pi<CT>();
+ CT const c1 = 1;
+ CT const cminus1 = -1;
+
+ // First, compute longitude on auxiliary sphere
+
+ CT const one_minus_f = c1 - f;
+ CT const bet1 = atan(one_minus_f * tan(lat1));
+ CT const bet2 = atan(one_minus_f * tan(lat2));
+ CT const bet3 = atan(one_minus_f * tan(lat3));
+
+ CT cos_bet1 = cos(bet1);
+ CT cos_bet2 = cos(bet2);
+ CT const sin_bet1 = sin(bet1);
+ CT const sin_bet2 = sin(bet2);
+ CT const sin_bet3 = sin(bet3);
+
+ CT omg12 = 0;
+
+ if (bet1 < c0)
+ {
+ cos_bet1 *= cminus1;
+ omg12 += pi;
+ }
+ if (bet2 < c0)
+ {
+ cos_bet2 *= cminus1;
+ omg12 += pi;
+ }
+
+ CT const sin_alp1 = sin(alp1);
+ CT const cos_alp1 = math::sqrt(c1 - math::sqr(sin_alp1));
+
+ CT const norm = math::sqrt(math::sqr(cos_alp1) + math::sqr(sin_alp1 * sin_bet1));
+ CT const sin_alp0 = sin(atan2(sin_alp1 * cos_bet1, norm));
+
+ BOOST_ASSERT(cos_bet2 != c0);
+ CT const sin_alp2 = sin_alp1 * cos_bet1 / cos_bet2;
+
+ CT const cos_alp0 = math::sqrt(c1 - math::sqr(sin_alp0));
+ CT const cos_alp2 = math::sqrt(c1 - math::sqr(sin_alp2));
+
+ CT const sig1 = atan2(sin_bet1, cos_alp1 * cos_bet1);
+ CT const sig2 = atan2(sin_bet2, -cos_alp2 * cos_bet2); //lat3 is a vertex
+
+ CT const cos_sig1 = cos(sig1);
+ CT const sin_sig1 = math::sqrt(c1 - math::sqr(cos_sig1));
+
+ CT const cos_sig2 = cos(sig2);
+ CT const sin_sig2 = math::sqrt(c1 - math::sqr(cos_sig2));
+
+ CT const omg1 = atan2(sin_alp0 * sin_sig1, cos_sig1);
+ CT const omg2 = atan2(sin_alp0 * sin_sig2, cos_sig2);
+
+ omg12 += omg1 - omg2;
+
+ CT const sin_omg12 = sin(omg12);
+ CT const cos_omg12 = cos(omg12);
+
+ CT omg13 = geometry::formula::vertex_longitude_on_sphere<CT>
+ ::apply(bet1, bet2, bet3, sin_omg12, cos_omg12);
+
+ if (lat1 * lat2 < c0)//different hemispheres
+ {
+ if ((lat2 - lat1) * lat3 > c0)// ascending segment
+ {
+ omg13 = pi - omg13;
+ }
+ }
+
+ // Second, compute the ellipsoidal longitude
+
+ CT const e2 = f * (c2 - f);
+ CT const ep = math::sqrt(e2 / (c1 - e2));
+ CT const k2 = math::sqr(ep * cos_alp0);
+ CT const sqrt_k2_plus_one = math::sqrt(c1 + k2);
+ CT const eps = (sqrt_k2_plus_one - c1) / (sqrt_k2_plus_one + c1);
+ CT const eps2 = eps * eps;
+ CT const n = f / (c2 - f);
+
+ // sig3 is the length from equator to the vertex
+ CT sig3;
+ if(sin_bet3 > c0)
+ {
+ sig3 = half_pi;
+ } else {
+ sig3 = -half_pi;
+ }
+ CT const cos_sig3 = 0;
+ CT const sin_sig3 = 1;
+
+ CT sig13 = sig3 - sig1;
+ if (sig13 > pi)
+ {
+ sig13 -= 2 * pi;
+ }
+
+ // Order 2 approximation
+ CT const c1over2 = 0.5;
+ CT const c1over4 = 0.25;
+ CT const c1over8 = 0.125;
+ CT const c1over16 = 0.0625;
+ CT const c4 = 4;
+ CT const c8 = 8;
+
+ CT const A3 = 1 - (c1over2 - c1over2 * n) * eps - c1over4 * eps2;
+ CT const C31 = (c1over4 - c1over4 * n) * eps + c1over8 * eps2;
+ CT const C32 = c1over16 * eps2;
+
+ CT const sin2_sig3 = c2 * cos_sig3 * sin_sig3;
+ CT const sin4_sig3 = sin_sig3 * (-c4 * cos_sig3
+ + c8 * cos_sig3 * cos_sig3 * cos_sig3);
+ CT const sin2_sig1 = c2 * cos_sig1 * sin_sig1;
+ CT const sin4_sig1 = sin_sig1 * (-c4 * cos_sig1
+ + c8 * cos_sig1 * cos_sig1 * cos_sig1);
+ CT const I3 = A3 * (sig13
+ + C31 * (sin2_sig3 - sin2_sig1)
+ + C32 * (sin4_sig3 - sin4_sig1));
+
+ int sign = c1;
+ if (bet3 < c0)
+ {
+ sign = cminus1;
+ }
+
+ CT const dlon_max = omg13 - sign * f * sin_alp0 * I3;
+
+ return dlon_max;
+ }
+};
+
+//CS_tag dispatching
+
+template <typename CT, typename CS_Tag>
+struct compute_vertex_lon
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_COORDINATE_SYSTEM, (types<CS_Tag>)
+ );
+
+};
+
+template <typename CT>
+struct compute_vertex_lon<CT, spherical_equatorial_tag>
+{
+ template <typename Strategy>
+ static inline CT apply(CT const& lat1,
+ CT const& lat2,
+ CT const& vertex_lat,
+ CT const& sin_l12,
+ CT const& cos_l12,
+ CT,
+ Strategy)
+ {
+ return vertex_longitude_on_sphere<CT>
+ ::apply(lat1,
+ lat2,
+ vertex_lat,
+ sin_l12,
+ cos_l12);
+ }
+};
+
+template <typename CT>
+struct compute_vertex_lon<CT, geographic_tag>
+{
+ template <typename Strategy>
+ static inline CT apply(CT const& lat1,
+ CT const& lat2,
+ CT const& vertex_lat,
+ CT,
+ CT,
+ CT& alp1,
+ Strategy const& azimuth_strategy)
+ {
+ return vertex_longitude_on_spheroid<CT>
+ ::apply(lat1,
+ lat2,
+ vertex_lat,
+ alp1,
+ azimuth_strategy.model());
+ }
+};
+
+// Vertex longitude interface
+// Assume that lon1 < lon2 and vertex_lat is the latitude of the vertex
+
+template <typename CT, typename CS_Tag>
+class vertex_longitude
+{
+public :
+ template <typename Strategy>
+ static inline CT apply(CT& lon1,
+ CT& lat1,
+ CT& lon2,
+ CT& lat2,
+ CT const& vertex_lat,
+ CT& alp1,
+ Strategy const& azimuth_strategy)
+ {
+ CT const c0 = 0;
+ CT pi = math::pi<CT>();
+
+ //Vertex is a segment's point
+ if (math::equals(vertex_lat, lat1))
+ {
+ return lon1;
+ }
+ if (math::equals(vertex_lat, lat2))
+ {
+ return lon2;
+ }
+
+ //Segment lay on meridian
+ if (math::equals(lon1, lon2))
+ {
+ return (std::max)(lat1, lat2);
+ }
+ BOOST_ASSERT(lon1 < lon2);
+
+ CT dlon = compute_vertex_lon<CT, CS_Tag>::apply(lat1, lat2,
+ vertex_lat,
+ sin(lon1 - lon2),
+ cos(lon1 - lon2),
+ alp1,
+ azimuth_strategy);
+
+ CT vertex_lon = std::fmod(lon1 + dlon, 2 * pi);
+
+ if (vertex_lat < c0)
+ {
+ vertex_lon -= pi;
+ }
+
+ if (std::abs(lon1 - lon2) > pi)
+ {
+ vertex_lon -= pi;
+ }
+
+ return vertex_lon;
+ }
+};
+
+}}} // namespace boost::geometry::formula
+#endif // BOOST_GEOMETRY_FORMULAS_MAXIMUM_LONGITUDE_HPP
+
diff --git a/boost/geometry/index/detail/algorithms/intersection_content.hpp b/boost/geometry/index/detail/algorithms/intersection_content.hpp
index 04dd4728be..437f90b46c 100644
--- a/boost/geometry/index/detail/algorithms/intersection_content.hpp
+++ b/boost/geometry/index/detail/algorithms/intersection_content.hpp
@@ -2,7 +2,7 @@
//
// boxes union/intersection area/volume
//
-// Copyright (c) 2011-2016 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -11,8 +11,9 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_INTERSECTION_CONTENT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_INTERSECTION_CONTENT_HPP
-#include <boost/geometry/algorithms/intersection.hpp>
-#include <boost/geometry/strategies/intersection_strategies.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
+#include <boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp>
+
#include <boost/geometry/index/detail/algorithms/content.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
@@ -23,11 +24,19 @@ namespace boost { namespace geometry { namespace index { namespace detail {
template <typename Box>
inline typename default_content_result<Box>::type intersection_content(Box const& box1, Box const& box2)
{
- if ( geometry::intersects(box1, box2) )
+ bool const intersects = ! geometry::detail::disjoint::box_box<Box, Box>::apply(box1, box2);
+
+ if ( intersects )
{
Box box_intersection;
- if ( geometry::intersection(box1, box2, box_intersection) )
- return detail::content(box_intersection);
+ bool const ok = geometry::detail::intersection::intersection_box_box
+ <
+ 0, geometry::dimension<Box>::value
+ >::apply(box1, box2, 0, box_intersection, 0);
+ if ( ok )
+ {
+ return index::detail::content(box_intersection);
+ }
}
return 0;
}
diff --git a/boost/geometry/index/detail/algorithms/path_intersection.hpp b/boost/geometry/index/detail/algorithms/path_intersection.hpp
index fe92596ba2..3cfb556c30 100644
--- a/boost/geometry/index/detail/algorithms/path_intersection.hpp
+++ b/boost/geometry/index/detail/algorithms/path_intersection.hpp
@@ -2,7 +2,7 @@
//
// n-dimensional box-linestring intersection
//
-// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -11,8 +11,12 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_PATH_INTERSECTION_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_PATH_INTERSECTION_HPP
+
#include <boost/geometry/index/detail/algorithms/segment_intersection.hpp>
+#include <boost/geometry/strategies/default_length_result.hpp>
+
+
namespace boost { namespace geometry { namespace index { namespace detail {
namespace dispatch {
diff --git a/boost/geometry/index/detail/rtree/node/variant_dynamic.hpp b/boost/geometry/index/detail/rtree/node/variant_dynamic.hpp
index 8e052e5216..e63cfd39ac 100644
--- a/boost/geometry/index/detail/rtree/node/variant_dynamic.hpp
+++ b/boost/geometry/index/detail/rtree/node/variant_dynamic.hpp
@@ -11,6 +11,8 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_DYNAMIC_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_DYNAMIC_HPP
+#include <boost/core/pointer_traits.hpp>
+
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
@@ -183,7 +185,7 @@ struct create_variant_node
scoped_deallocator<AllocNode> deallocator(p, alloc_node);
- Al::construct(alloc_node, boost::addressof(*p), Node(alloc_node)); // implicit cast to Variant
+ Al::construct(alloc_node, boost::pointer_traits<P>::to_address(p), Node(alloc_node)); // implicit cast to Variant
deallocator.release();
return p;
diff --git a/boost/geometry/index/detail/rtree/node/weak_dynamic.hpp b/boost/geometry/index/detail/rtree/node/weak_dynamic.hpp
index d49e347826..05fef59e52 100644
--- a/boost/geometry/index/detail/rtree/node/weak_dynamic.hpp
+++ b/boost/geometry/index/detail/rtree/node/weak_dynamic.hpp
@@ -199,7 +199,7 @@ struct create_weak_node
scoped_deallocator<AllocNode> deallocator(p, alloc_node);
- Al::construct(alloc_node, boost::addressof(*p), alloc_node);
+ Al::construct(alloc_node, boost::pointer_traits<P>::to_address(p), alloc_node);
deallocator.release();
return p;
diff --git a/boost/geometry/index/detail/rtree/visitors/remove.hpp b/boost/geometry/index/detail/rtree/visitors/remove.hpp
index 6326f87db6..7e6162a616 100644
--- a/boost/geometry/index/detail/rtree/visitors/remove.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/remove.hpp
@@ -2,7 +2,7 @@
//
// R-tree removing visitor implementation
//
-// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -13,7 +13,7 @@
#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
-#include <boost/geometry/algorithms/covered_by.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
namespace boost { namespace geometry { namespace index {
diff --git a/boost/geometry/index/equal_to.hpp b/boost/geometry/index/equal_to.hpp
index 6b722a89fc..2fb1ed216c 100644
--- a/boost/geometry/index/equal_to.hpp
+++ b/boost/geometry/index/equal_to.hpp
@@ -9,7 +9,7 @@
#ifndef BOOST_GEOMETRY_INDEX_EQUAL_TO_HPP
#define BOOST_GEOMETRY_INDEX_EQUAL_TO_HPP
-#include <boost/geometry/algorithms/equals.hpp>
+#include <boost/geometry/algorithms/detail/equals/interface.hpp>
#include <boost/geometry/index/indexable.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
diff --git a/boost/geometry/index/indexable.hpp b/boost/geometry/index/indexable.hpp
index feaae557af..831e17f6dd 100644
--- a/boost/geometry/index/indexable.hpp
+++ b/boost/geometry/index/indexable.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry Index
//
-// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -10,6 +10,7 @@
#define BOOST_GEOMETRY_INDEX_INDEXABLE_HPP
#include <boost/mpl/assert.hpp>
+#include <boost/tuple/tuple.hpp>
#include <boost/geometry/index/detail/is_indexable.hpp>
diff --git a/boost/geometry/index/rtree.hpp b/boost/geometry/index/rtree.hpp
index 6d3704ff8c..439880ad5a 100644
--- a/boost/geometry/index/rtree.hpp
+++ b/boost/geometry/index/rtree.hpp
@@ -3,7 +3,7 @@
// R-tree implementation
//
// Copyright (c) 2008 Federico J. Fernandez.
-// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -21,20 +21,18 @@
// Boost.Geometry
#include <boost/geometry/algorithms/detail/comparable_distance/interface.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/interface.hpp>
+#include <boost/geometry/algorithms/detail/equals/interface.hpp>
+#include <boost/geometry/algorithms/detail/intersects/interface.hpp>
+#include <boost/geometry/algorithms/detail/overlaps/interface.hpp>
+#include <boost/geometry/algorithms/detail/touches/interface.hpp>
+#include <boost/geometry/algorithms/detail/within/interface.hpp>
#include <boost/geometry/algorithms/centroid.hpp>
-#include <boost/geometry/algorithms/covered_by.hpp>
-#include <boost/geometry/algorithms/disjoint.hpp>
-#include <boost/geometry/algorithms/equals.hpp>
-#include <boost/geometry/algorithms/intersects.hpp>
-#include <boost/geometry/algorithms/overlaps.hpp>
-#include <boost/geometry/algorithms/touches.hpp>
-#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/box.hpp>
-#include <boost/geometry/strategies/strategies.hpp>
-
// Boost.Geometry.Index
#include <boost/geometry/index/detail/config_begin.hpp>
@@ -145,7 +143,8 @@ compared left-to-right.
\tparam Allocator The allocator used to allocate/deallocate memory,
construct/destroy nodes and Values.
*/
-template <
+template
+<
typename Value,
typename Parameters,
typename IndexableGetter = index::indexable<Value>,
@@ -2222,9 +2221,6 @@ struct range_mutable_iterator
} // namespace boost
-// TODO: don't include the implementation at the end of the file
-#include <boost/geometry/algorithms/detail/comparable_distance/implementation.hpp>
-
#include <boost/geometry/index/detail/config_end.hpp>
#endif // BOOST_GEOMETRY_INDEX_RTREE_HPP
diff --git a/boost/geometry/strategies/agnostic/point_in_point.hpp b/boost/geometry/strategies/agnostic/point_in_point.hpp
index c6e2b63623..1a9274149a 100644
--- a/boost/geometry/strategies/agnostic/point_in_point.hpp
+++ b/boost/geometry/strategies/agnostic/point_in_point.hpp
@@ -42,10 +42,14 @@ struct point_in_point
namespace services
{
-template <typename Point, typename PointLike, typename Tag2, typename AnyCS1, typename AnyCS2>
-struct default_strategy<Point, PointLike, point_tag, Tag2, pointlike_tag, pointlike_tag, AnyCS1, AnyCS2>
+template <typename PointLike1, typename PointLike2, typename Tag1, typename Tag2, typename AnyCS1, typename AnyCS2>
+struct default_strategy<PointLike1, PointLike2, Tag1, Tag2, pointlike_tag, pointlike_tag, AnyCS1, AnyCS2>
{
- typedef strategy::within::point_in_point<Point, typename point_type<PointLike>::type> type;
+ typedef strategy::within::point_in_point
+ <
+ typename point_type<PointLike1>::type,
+ typename point_type<PointLike2>::type
+ > type;
};
@@ -61,10 +65,14 @@ struct default_strategy<Point, PointLike, point_tag, Tag2, pointlike_tag, pointl
namespace strategy { namespace covered_by { namespace services
{
-template <typename Point, typename PointLike, typename Tag2, typename AnyCS1, typename AnyCS2>
-struct default_strategy<Point, PointLike, point_tag, Tag2, pointlike_tag, pointlike_tag, AnyCS1, AnyCS2>
+template <typename PointLike1, typename PointLike2, typename Tag1, typename Tag2, typename AnyCS1, typename AnyCS2>
+struct default_strategy<PointLike1, PointLike2, Tag1, Tag2, pointlike_tag, pointlike_tag, AnyCS1, AnyCS2>
{
- typedef strategy::within::point_in_point<Point, typename point_type<PointLike>::type> type;
+ typedef strategy::within::point_in_point
+ <
+ typename point_type<PointLike1>::type,
+ typename point_type<PointLike2>::type
+ > type;
};
}}} // namespace strategy::covered_by::services
diff --git a/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp b/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp
index 3e7e258788..0a797ac0f0 100644
--- a/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp
+++ b/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp
@@ -388,6 +388,20 @@ class winding
public:
+ typedef typename SideStrategy::envelope_strategy_type envelope_strategy_type;
+
+ inline envelope_strategy_type get_envelope_strategy() const
+ {
+ return m_side_strategy.get_envelope_strategy();
+ }
+
+ typedef typename SideStrategy::disjoint_strategy_type disjoint_strategy_type;
+
+ inline disjoint_strategy_type get_disjoint_strategy() const
+ {
+ return m_side_strategy.get_disjoint_strategy();
+ }
+
winding()
{}
@@ -459,28 +473,44 @@ private:
namespace services
{
-template <typename Point, typename Geometry, typename AnyTag>
-struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
+template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
+struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
- typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
+ typedef winding
+ <
+ typename geometry::point_type<PointLike>::type,
+ typename geometry::point_type<Geometry>::type
+ > type;
};
-template <typename Point, typename Geometry, typename AnyTag>
-struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, polygonal_tag, spherical_tag, spherical_tag>
+template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
+struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, spherical_tag, spherical_tag>
{
- typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
+ typedef winding
+ <
+ typename geometry::point_type<PointLike>::type,
+ typename geometry::point_type<Geometry>::type
+ > type;
};
-template <typename Point, typename Geometry, typename AnyTag>
-struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
+template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
+struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
{
- typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
+ typedef winding
+ <
+ typename geometry::point_type<PointLike>::type,
+ typename geometry::point_type<Geometry>::type
+ > type;
};
-template <typename Point, typename Geometry, typename AnyTag>
-struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linear_tag, spherical_tag, spherical_tag>
+template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
+struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, spherical_tag, spherical_tag>
{
- typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
+ typedef winding
+ <
+ typename geometry::point_type<PointLike>::type,
+ typename geometry::point_type<Geometry>::type
+ > type;
};
} // namespace services
@@ -495,28 +525,44 @@ struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linea
namespace strategy { namespace covered_by { namespace services
{
-template <typename Point, typename Geometry, typename AnyTag>
-struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
+template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
+struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
- typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
+ typedef within::winding
+ <
+ typename geometry::point_type<PointLike>::type,
+ typename geometry::point_type<Geometry>::type
+ > type;
};
-template <typename Point, typename Geometry, typename AnyTag>
-struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, polygonal_tag, spherical_tag, spherical_tag>
+template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
+struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, spherical_tag, spherical_tag>
{
- typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
+ typedef within::winding
+ <
+ typename geometry::point_type<PointLike>::type,
+ typename geometry::point_type<Geometry>::type
+ > type;
};
-template <typename Point, typename Geometry, typename AnyTag>
-struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
+template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
+struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
{
- typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
+ typedef within::winding
+ <
+ typename geometry::point_type<PointLike>::type,
+ typename geometry::point_type<Geometry>::type
+ > type;
};
-template <typename Point, typename Geometry, typename AnyTag>
-struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linear_tag, spherical_tag, spherical_tag>
+template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
+struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, spherical_tag, spherical_tag>
{
- typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
+ typedef within::winding
+ <
+ typename geometry::point_type<PointLike>::type,
+ typename geometry::point_type<Geometry>::type
+ > type;
};
}}} // namespace strategy::covered_by::services
diff --git a/boost/geometry/strategies/cartesian/disjoint_segment_box.hpp b/boost/geometry/strategies/cartesian/disjoint_segment_box.hpp
index 4270803322..4da4bc4503 100644
--- a/boost/geometry/strategies/cartesian/disjoint_segment_box.hpp
+++ b/boost/geometry/strategies/cartesian/disjoint_segment_box.hpp
@@ -8,8 +8,9 @@
// This file was modified by Oracle on 2013-2017.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -293,16 +294,14 @@ struct segment_box
namespace services
{
-// Currently used in all coordinate systems
-
template <typename Linear, typename Box, typename LinearTag>
-struct default_strategy<Linear, Box, LinearTag, box_tag, 1, 2>
+struct default_strategy<Linear, Box, LinearTag, box_tag, 1, 2, cartesian_tag, cartesian_tag>
{
typedef disjoint::segment_box type;
};
template <typename Box, typename Linear, typename LinearTag>
-struct default_strategy<Box, Linear, box_tag, LinearTag, 2, 1>
+struct default_strategy<Box, Linear, box_tag, LinearTag, 2, 1, cartesian_tag, cartesian_tag>
{
typedef disjoint::segment_box type;
};
diff --git a/boost/geometry/strategies/cartesian/envelope_segment.hpp b/boost/geometry/strategies/cartesian/envelope_segment.hpp
index 0ddbf12a41..a591996b84 100644
--- a/boost/geometry/strategies/cartesian/envelope_segment.hpp
+++ b/boost/geometry/strategies/cartesian/envelope_segment.hpp
@@ -14,6 +14,7 @@
#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/strategies/envelope.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
diff --git a/boost/geometry/strategies/cartesian/intersection.hpp b/boost/geometry/strategies/cartesian/intersection.hpp
index 20b6b93367..50e903885b 100644
--- a/boost/geometry/strategies/cartesian/intersection.hpp
+++ b/boost/geometry/strategies/cartesian/intersection.hpp
@@ -36,6 +36,7 @@
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/cartesian/area_surveyor.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
+#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/intersection.hpp>
@@ -133,6 +134,14 @@ struct cartesian_segments
return strategy_type();
}
+ typedef envelope::cartesian_segment<CalculationType>
+ envelope_strategy_type;
+
+ static inline envelope_strategy_type get_envelope_strategy()
+ {
+ return envelope_strategy_type();
+ }
+
template <typename CoordinateType, typename SegmentRatio>
struct segment_intersection_info
{
diff --git a/boost/geometry/strategies/cartesian/side_by_triangle.hpp b/boost/geometry/strategies/cartesian/side_by_triangle.hpp
index ba7749ba76..4d1d97520f 100644
--- a/boost/geometry/strategies/cartesian/side_by_triangle.hpp
+++ b/boost/geometry/strategies/cartesian/side_by_triangle.hpp
@@ -26,6 +26,9 @@
#include <boost/geometry/arithmetic/determinant.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
+
+#include <boost/geometry/strategies/cartesian/disjoint_segment_box.hpp>
+#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/algorithms/detail/relate/less.hpp>
@@ -66,6 +69,19 @@ class side_by_triangle
};
public :
+ typedef strategy::envelope::cartesian_segment<CalculationType> envelope_strategy_type;
+
+ static inline envelope_strategy_type get_envelope_strategy()
+ {
+ return envelope_strategy_type();
+ }
+
+ typedef strategy::disjoint::segment_box disjoint_strategy_type;
+
+ static inline disjoint_strategy_type get_disjoint_strategy()
+ {
+ return disjoint_strategy_type();
+ }
// Template member function, because it is not always trivial
// or convenient to explicitly mention the typenames in the
diff --git a/boost/geometry/strategies/disjoint.hpp b/boost/geometry/strategies/disjoint.hpp
index f844cd86ad..23d2cede49 100644
--- a/boost/geometry/strategies/disjoint.hpp
+++ b/boost/geometry/strategies/disjoint.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry
// Copyright (c) 2017, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -37,7 +38,9 @@ template
typename Tag1 = typename geometry::tag<Geometry1>::type,
typename Tag2 = typename geometry::tag<Geometry2>::type,
int TopDim1 = geometry::topological_dimension<Geometry1>::value,
- int TopDim2 = geometry::topological_dimension<Geometry2>::value
+ int TopDim2 = geometry::topological_dimension<Geometry2>::value,
+ typename CsTag1 = typename cs_tag<Geometry1>::type,
+ typename CsTag2 = typename cs_tag<Geometry2>::type
>
struct default_strategy
: relate::services::default_strategy
diff --git a/boost/geometry/strategies/geographic/area.hpp b/boost/geometry/strategies/geographic/area.hpp
index e1d3b09b5a..44dc2e6945 100644
--- a/boost/geometry/strategies/geographic/area.hpp
+++ b/boost/geometry/strategies/geographic/area.hpp
@@ -83,7 +83,7 @@ protected :
CT const m_e2; // squared eccentricity
CT const m_ep2; // squared second eccentricity
CT const m_ep; // second eccentricity
- CT const m_c2; // authalic radius
+ CT const m_c2; // squared authalic radius
inline spheroid_constants(Spheroid const& spheroid)
: m_spheroid(spheroid)
@@ -92,12 +92,27 @@ protected :
* (CT(2.0) - CT(formula::flattening<CT>(spheroid))))
, m_ep2(m_e2 / (CT(1.0) - m_e2))
, m_ep(math::sqrt(m_ep2))
- , m_c2((m_a2 / CT(2.0)) +
- ((math::sqr(get_radius<2>(spheroid)) * boost::math::atanh(math::sqrt(m_e2)))
- / (CT(2.0) * math::sqrt(m_e2))))
+ , m_c2(authalic_radius(spheroid, m_a2, m_e2))
{}
};
+ static inline CT authalic_radius(Spheroid const& sph, CT const& a2, CT const& e2)
+ {
+ CT const c0 = 0;
+
+ if (math::equals(e2, c0))
+ {
+ return a2;
+ }
+
+ CT const sqrt_e2 = math::sqrt(e2);
+ CT const c2 = 2;
+
+ return (a2 / c2) +
+ ((math::sqr(get_radius<2>(sph)) * boost::math::atanh(sqrt_e2))
+ / (c2 * sqrt_e2));
+ }
+
struct area_sums
{
CT m_excess_sum;
diff --git a/boost/geometry/strategies/geographic/azimuth.hpp b/boost/geometry/strategies/geographic/azimuth.hpp
index 47f59d1033..79c49750fb 100644
--- a/boost/geometry/strategies/geographic/azimuth.hpp
+++ b/boost/geometry/strategies/geographic/azimuth.hpp
@@ -71,6 +71,24 @@ public :
a2 = i_res.reverse_azimuth;
}
+ template <typename T>
+ inline void apply(T const& lon1_rad, T const& lat1_rad,
+ T const& lon2_rad, T const& lat2_rad,
+ T& a1) const
+ {
+ typedef typename boost::mpl::if_
+ <
+ boost::is_void<CalculationType>, T, CalculationType
+ >::type calc_t;
+
+ typedef typename FormulaPolicy::template inverse<calc_t, false, true, false, false, false> inverse_type;
+ typedef typename inverse_type::result_type inverse_result;
+ inverse_result i_res = inverse_type::apply(calc_t(lon1_rad), calc_t(lat1_rad),
+ calc_t(lon2_rad), calc_t(lat2_rad),
+ m_spheroid);
+ a1 = i_res.azimuth;
+ }
+
private :
Spheroid m_spheroid;
};
diff --git a/boost/geometry/strategies/geographic/disjoint_segment_box.hpp b/boost/geometry/strategies/geographic/disjoint_segment_box.hpp
new file mode 100644
index 0000000000..afc9d66775
--- /dev/null
+++ b/boost/geometry/strategies/geographic/disjoint_segment_box.hpp
@@ -0,0 +1,130 @@
+// Boost.Geometry
+
+// Copyright (c) 2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the 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_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISJOINT_SEGMENT_BOX_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISJOINT_SEGMENT_BOX_HPP
+
+
+#include <cstddef>
+#include <utility>
+
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/calculation_type.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/point_type.hpp>
+
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
+
+#include <boost/geometry/strategies/disjoint.hpp>
+#include <boost/geometry/strategies/geographic/azimuth.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
+
+
+namespace boost { namespace geometry { namespace strategy { namespace disjoint
+{
+
+// NOTE: This may be temporary place for this or corresponding strategy
+// It seems to be more appropriate to implement the opposite of it
+// e.g. intersection::segment_box because in disjoint() algorithm
+// other strategies that are used are intersection and covered_by strategies.
+template
+<
+ typename FormulaPolicy = strategy::andoyer,
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+struct segment_box_geographic
+{
+public:
+ typedef Spheroid model_type;
+
+ inline segment_box_geographic()
+ : m_spheroid()
+ {}
+
+ explicit inline segment_box_geographic(Spheroid const& spheroid)
+ : m_spheroid(spheroid)
+ {}
+
+ template <typename Segment, typename Box>
+ struct point_in_geometry_strategy
+ : services::default_strategy
+ <
+ typename point_type<Segment>::type,
+ Box
+ >
+ {};
+
+ template <typename Segment, typename Box>
+ static inline typename point_in_geometry_strategy<Segment, Box>::type
+ get_point_in_geometry_strategy()
+ {
+ typedef typename point_in_geometry_strategy<Segment, Box>::type strategy_type;
+
+ return strategy_type();
+ }
+
+ template <typename Segment, typename Box>
+ inline bool apply(Segment const& segment, Box const& box) const
+ {
+ geometry::strategy::azimuth::geographic
+ <
+ FormulaPolicy,
+ Spheroid,
+ CalculationType
+ > azimuth_geographic(m_spheroid);
+
+ return geometry::detail::disjoint::disjoint_segment_box_sphere_or_spheroid
+ <geographic_tag>::apply(segment, box, azimuth_geographic);
+ }
+
+private:
+ Spheroid m_spheroid;
+};
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+namespace services
+{
+
+template <typename Linear, typename Box, typename LinearTag>
+struct default_strategy<Linear, Box, LinearTag, box_tag, 1, 2,
+ geographic_tag, geographic_tag>
+{
+ typedef segment_box_geographic<> type;
+};
+
+template <typename Box, typename Linear, typename LinearTag>
+struct default_strategy<Box, Linear, box_tag, LinearTag, 2, 1,
+ geographic_tag, geographic_tag>
+{
+ typedef segment_box_geographic<> type;
+};
+
+
+} // namespace services
+
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}}}} // namespace boost::geometry::strategy::disjoint
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISJOINT_SEGMENT_BOX_HPP
diff --git a/boost/geometry/strategies/geographic/intersection.hpp b/boost/geometry/strategies/geographic/intersection.hpp
index 1708c274c0..59a40f281d 100644
--- a/boost/geometry/strategies/geographic/intersection.hpp
+++ b/boost/geometry/strategies/geographic/intersection.hpp
@@ -34,6 +34,7 @@
#include <boost/geometry/strategies/geographic/area.hpp>
#include <boost/geometry/strategies/geographic/distance.hpp>
+#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/strategies/geographic/side.hpp>
#include <boost/geometry/strategies/intersection.hpp>
@@ -135,6 +136,14 @@ struct geographic_segments
return strategy_type(m_spheroid);
}
+ typedef envelope::geographic_segment<FormulaPolicy, Spheroid, CalculationType>
+ envelope_strategy_type;
+
+ inline envelope_strategy_type get_envelope_strategy() const
+ {
+ return envelope_strategy_type(m_spheroid);
+ }
+
enum intersection_point_flag { ipi_inters = 0, ipi_at_a1, ipi_at_a2, ipi_at_b1, ipi_at_b2 };
template <typename CoordinateType, typename SegmentRatio>
@@ -280,6 +289,8 @@ private:
typedef typename select_calculation_type
<Segment1, Segment2, CalculationType>::type calc_t;
+ static const calc_t c0 = 0;
+
// normalized spheroid
srs::spheroid<calc_t> spheroid = normalized_spheroid<calc_t>(m_spheroid);
@@ -316,31 +327,80 @@ private:
// TODO: no need to call inverse formula if we know that the points are equal
// distance can be set to 0 in this case and azimuth may be not calculated
- bool const is_equal_a1_b1 = equals_point_point(a1, b1);
- bool const is_equal_a2_b1 = equals_point_point(a2, b1);
+ bool is_equal_a1_b1 = equals_point_point(a1, b1);
+ bool is_equal_a2_b1 = equals_point_point(a2, b1);
+ bool degen_neq_coords = false;
- inverse_result res_b1_b2 = inverse_dist_azi::apply(b1_lon, b1_lat, b2_lon, b2_lat, spheroid);
- inverse_result res_b1_a1 = inverse_dist_azi::apply(b1_lon, b1_lat, a1_lon, a1_lat, spheroid);
- inverse_result res_b1_a2 = inverse_dist_azi::apply(b1_lon, b1_lat, a2_lon, a2_lat, spheroid);
- sides.set<0>(is_equal_a1_b1 ? 0 : formula::azimuth_side_value(res_b1_a1.azimuth, res_b1_b2.azimuth),
- is_equal_a2_b1 ? 0 : formula::azimuth_side_value(res_b1_a2.azimuth, res_b1_b2.azimuth));
- if (sides.same<0>())
+ inverse_result res_b1_b2, res_b1_a1, res_b1_a2;
+ if (! b_is_point)
{
- // Both points are at the same side of other segment, we can leave
- return Policy::disjoint();
+ res_b1_b2 = inverse_dist_azi::apply(b1_lon, b1_lat, b2_lon, b2_lat, spheroid);
+ if (math::equals(res_b1_b2.distance, c0))
+ {
+ b_is_point = true;
+ degen_neq_coords = true;
+ }
+ else
+ {
+ res_b1_a1 = inverse_dist_azi::apply(b1_lon, b1_lat, a1_lon, a1_lat, spheroid);
+ if (math::equals(res_b1_a1.distance, c0))
+ {
+ is_equal_a1_b1 = true;
+ }
+ res_b1_a2 = inverse_dist_azi::apply(b1_lon, b1_lat, a2_lon, a2_lat, spheroid);
+ if (math::equals(res_b1_a2.distance, c0))
+ {
+ is_equal_a2_b1 = true;
+ }
+ sides.set<0>(is_equal_a1_b1 ? 0 : formula::azimuth_side_value(res_b1_a1.azimuth, res_b1_b2.azimuth),
+ is_equal_a2_b1 ? 0 : formula::azimuth_side_value(res_b1_a2.azimuth, res_b1_b2.azimuth));
+ if (sides.same<0>())
+ {
+ // Both points are at the same side of other segment, we can leave
+ return Policy::disjoint();
+ }
+ }
}
- bool const is_equal_a1_b2 = equals_point_point(a1, b2);
+ bool is_equal_a1_b2 = equals_point_point(a1, b2);
- inverse_result res_a1_a2 = inverse_dist_azi::apply(a1_lon, a1_lat, a2_lon, a2_lat, spheroid);
- inverse_result res_a1_b1 = inverse_dist_azi::apply(a1_lon, a1_lat, b1_lon, b1_lat, spheroid);
- inverse_result res_a1_b2 = inverse_dist_azi::apply(a1_lon, a1_lat, b2_lon, b2_lat, spheroid);
- sides.set<1>(is_equal_a1_b1 ? 0 : formula::azimuth_side_value(res_a1_b1.azimuth, res_a1_a2.azimuth),
- is_equal_a1_b2 ? 0 : formula::azimuth_side_value(res_a1_b2.azimuth, res_a1_a2.azimuth));
- if (sides.same<1>())
+ inverse_result res_a1_a2, res_a1_b1, res_a1_b2;
+ if (! a_is_point)
{
- // Both points are at the same side of other segment, we can leave
- return Policy::disjoint();
+ res_a1_a2 = inverse_dist_azi::apply(a1_lon, a1_lat, a2_lon, a2_lat, spheroid);
+ if (math::equals(res_a1_a2.distance, c0))
+ {
+ a_is_point = true;
+ degen_neq_coords = true;
+ }
+ else
+ {
+ res_a1_b1 = inverse_dist_azi::apply(a1_lon, a1_lat, b1_lon, b1_lat, spheroid);
+ if (math::equals(res_a1_b1.distance, c0))
+ {
+ is_equal_a1_b1 = true;
+ }
+ res_a1_b2 = inverse_dist_azi::apply(a1_lon, a1_lat, b2_lon, b2_lat, spheroid);
+ if (math::equals(res_a1_b2.distance, c0))
+ {
+ is_equal_a1_b2 = true;
+ }
+ sides.set<1>(is_equal_a1_b1 ? 0 : formula::azimuth_side_value(res_a1_b1.azimuth, res_a1_a2.azimuth),
+ is_equal_a1_b2 ? 0 : formula::azimuth_side_value(res_a1_b2.azimuth, res_a1_a2.azimuth));
+ if (sides.same<1>())
+ {
+ // Both points are at the same side of other segment, we can leave
+ return Policy::disjoint();
+ }
+ }
+ }
+
+ if(a_is_point && b_is_point)
+ {
+ return is_equal_a1_b2
+ ? Policy::degenerate(a, true)
+ : Policy::disjoint()
+ ;
}
// NOTE: at this point the segments may still be disjoint
@@ -370,11 +430,11 @@ private:
{
if (a_is_point)
{
- return collinear_one_degenerated<Policy, calc_t>(a, true, b1, b2, a1, a2, res_b1_b2, res_b1_a1, is_b_reversed);
+ return collinear_one_degenerated<Policy, calc_t>(a, true, b1, b2, a1, a2, res_b1_b2, res_b1_a1, res_b1_a2, is_b_reversed, degen_neq_coords);
}
else if (b_is_point)
{
- return collinear_one_degenerated<Policy, calc_t>(b, false, a1, a2, b1, b2, res_a1_a2, res_a1_b1, is_a_reversed);
+ return collinear_one_degenerated<Policy, calc_t>(b, false, a1, a2, b1, b2, res_a1_a2, res_a1_b1, res_a1_b2, is_a_reversed, degen_neq_coords);
}
else
{
@@ -383,16 +443,16 @@ private:
// use shorter segment
if (res_a1_a2.distance <= res_b1_b2.distance)
{
- calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b1, dist_a1_a2, dist_a1_b1);
- calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b2, dist_a1_a2, dist_a1_b2);
+ calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b1, res_a1_b2, dist_a1_a2, dist_a1_b1);
+ calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b2, res_a1_b1, dist_a1_a2, dist_a1_b2);
dist_b1_b2 = dist_a1_b2 - dist_a1_b1;
dist_b1_a1 = -dist_a1_b1;
dist_b1_a2 = dist_a1_a2 - dist_a1_b1;
}
else
{
- calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a1, dist_b1_b2, dist_b1_a1);
- calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a2, dist_b1_b2, dist_b1_a2);
+ calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a1, res_b1_a2, dist_b1_b2, dist_b1_a1);
+ calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a2, res_b1_a1, dist_b1_b2, dist_b1_a2);
dist_a1_a2 = dist_b1_a2 - dist_b1_a1;
dist_a1_b1 = -dist_b1_a1;
dist_a1_b2 = dist_b1_b2 - dist_b1_a1;
@@ -540,11 +600,13 @@ private:
Point1 const& a1, Point1 const& a2,
Point2 const& b1, Point2 const& b2,
ResultInverse const& res_a1_a2,
- ResultInverse const& res_a1_bi,
- bool is_other_reversed)
+ ResultInverse const& res_a1_b1,
+ ResultInverse const& res_a1_b2,
+ bool is_other_reversed,
+ bool degen_neq_coords)
{
CalcT dist_1_2, dist_1_o;
- if (! calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_bi, dist_1_2, dist_1_o))
+ if (! calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b1, res_a1_b2, dist_1_2, dist_1_o, degen_neq_coords))
{
return Policy::disjoint();
}
@@ -565,13 +627,16 @@ private:
static inline bool calculate_collinear_data(Point1 const& a1, Point1 const& a2, // in
Point2 const& b1, Point2 const& b2, // in
ResultInverse const& res_a1_a2, // in
- ResultInverse const& res_a1_bi, // in
- CalcT& dist_a1_a2, CalcT& dist_a1_bi) // out
+ ResultInverse const& res_a1_b1, // in
+ ResultInverse const& res_a1_b2, // in
+ CalcT& dist_a1_a2, // out
+ CalcT& dist_a1_bi, // out
+ bool degen_neq_coords = false) // in
{
dist_a1_a2 = res_a1_a2.distance;
- dist_a1_bi = res_a1_bi.distance;
- if (! same_direction(res_a1_bi.azimuth, res_a1_a2.azimuth))
+ dist_a1_bi = res_a1_b1.distance;
+ if (! same_direction(res_a1_b1.azimuth, res_a1_a2.azimuth))
{
dist_a1_bi = -dist_a1_bi;
}
@@ -589,6 +654,22 @@ private:
return true;
}
+ // check the other endpoint of a very short segment near the pole
+ if (degen_neq_coords)
+ {
+ static CalcT const c0 = 0;
+ if (math::equals(res_a1_b2.distance, c0))
+ {
+ dist_a1_bi = 0;
+ return true;
+ }
+ else if (math::equals(dist_a1_a2 - res_a1_b2.distance, c0))
+ {
+ dist_a1_bi = dist_a1_a2;
+ return true;
+ }
+ }
+
// or i1 is on b
return segment_ratio<CalcT>(dist_a1_bi, dist_a1_a2).on_segment();
}
@@ -816,8 +897,9 @@ private:
static inline bool is_endpoint_equal(CalcT const& dist,
P1 const& ai, P2 const& b1, P2 const& b2)
{
+ static CalcT const c0 = 0;
using geometry::detail::equals::equals_point_point;
- return is_near(dist) && (equals_point_point(ai, b1) || equals_point_point(ai, b2));
+ return is_near(dist) && (equals_point_point(ai, b1) || equals_point_point(ai, b2) || math::equals(dist, c0));
}
template <typename CalcT>
diff --git a/boost/geometry/strategies/geographic/side.hpp b/boost/geometry/strategies/geographic/side.hpp
index 0d40e4da20..9276965a97 100644
--- a/boost/geometry/strategies/geographic/side.hpp
+++ b/boost/geometry/strategies/geographic/side.hpp
@@ -26,6 +26,8 @@
#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
+#include <boost/geometry/strategies/geographic/disjoint_segment_box.hpp>
+#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/strategies/side.hpp>
//#include <boost/geometry/strategies/concepts/side_concept.hpp>
@@ -56,6 +58,30 @@ template
class geographic
{
public:
+ typedef strategy::envelope::geographic_segment
+ <
+ FormulaPolicy,
+ Spheroid,
+ CalculationType
+ > envelope_strategy_type;
+
+ inline envelope_strategy_type get_envelope_strategy() const
+ {
+ return envelope_strategy_type(m_model);
+ }
+
+ typedef strategy::disjoint::segment_box_geographic
+ <
+ FormulaPolicy,
+ Spheroid,
+ CalculationType
+ > disjoint_strategy_type;
+
+ inline disjoint_strategy_type get_disjoint_strategy() const
+ {
+ return disjoint_strategy_type(m_model);
+ }
+
geographic()
{}
diff --git a/boost/geometry/strategies/spherical/azimuth.hpp b/boost/geometry/strategies/spherical/azimuth.hpp
index 3c208fe2e2..7a711c9814 100644
--- a/boost/geometry/strategies/spherical/azimuth.hpp
+++ b/boost/geometry/strategies/spherical/azimuth.hpp
@@ -55,6 +55,24 @@ public :
a2 = result.reverse_azimuth;
}
+ template <typename T>
+ inline void apply(T const& lon1_rad, T const& lat1_rad,
+ T const& lon2_rad, T const& lat2_rad,
+ T& a1) const
+ {
+ typedef typename boost::mpl::if_
+ <
+ boost::is_void<CalculationType>, T, CalculationType
+ >::type calc_t;
+
+ geometry::formula::result_spherical<calc_t>
+ result = geometry::formula::spherical_azimuth<calc_t, false>(
+ calc_t(lon1_rad), calc_t(lat1_rad),
+ calc_t(lon2_rad), calc_t(lat2_rad));
+
+ a1 = result.azimuth;
+ }
+
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
diff --git a/boost/geometry/strategies/spherical/disjoint_segment_box.hpp b/boost/geometry/strategies/spherical/disjoint_segment_box.hpp
new file mode 100644
index 0000000000..bda62a77fc
--- /dev/null
+++ b/boost/geometry/strategies/spherical/disjoint_segment_box.hpp
@@ -0,0 +1,105 @@
+// Boost.Geometry
+
+// Copyright (c) 2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the 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_GEOMETRY_STRATEGIES_SPHERICAL_DISJOINT_SEGMENT_BOX_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISJOINT_SEGMENT_BOX_HPP
+
+
+#include <cstddef>
+#include <utility>
+
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/calculation_type.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/point_type.hpp>
+
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
+
+#include <boost/geometry/strategies/spherical/azimuth.hpp>
+#include <boost/geometry/strategies/disjoint.hpp>
+
+namespace boost { namespace geometry { namespace strategy { namespace disjoint
+{
+
+// NOTE: This may be temporary place for this or corresponding strategy
+// It seems to be more appropriate to implement the opposite of it
+// e.g. intersection::segment_box because in disjoint() algorithm
+// other strategies that are used are intersection and covered_by strategies.
+struct segment_box_spherical
+{
+ template <typename Segment, typename Box>
+ struct point_in_geometry_strategy
+ : services::default_strategy
+ <
+ typename point_type<Segment>::type,
+ Box
+ >
+ {};
+
+ template <typename Segment, typename Box>
+ static inline typename point_in_geometry_strategy<Segment, Box>::type
+ get_point_in_geometry_strategy()
+ {
+ typedef typename point_in_geometry_strategy<Segment, Box>::type strategy_type;
+
+ return strategy_type();
+ }
+
+ template <typename Segment, typename Box>
+ static inline bool apply(Segment const& segment, Box const& box)
+ {
+ typedef typename point_type<Segment>::type segment_point_type;
+ typedef typename coordinate_type<segment_point_type>::type CT;
+ geometry::strategy::azimuth::spherical<CT> azimuth_strategy;
+
+ return geometry::detail::disjoint::disjoint_segment_box_sphere_or_spheroid
+ <spherical_equatorial_tag>::apply(segment, box, azimuth_strategy);
+ }
+};
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+namespace services
+{
+
+template <typename Linear, typename Box, typename LinearTag>
+struct default_strategy<Linear, Box, LinearTag, box_tag, 1, 2,
+ spherical_equatorial_tag, spherical_equatorial_tag>
+{
+ typedef segment_box_spherical type;
+};
+
+template <typename Box, typename Linear, typename LinearTag>
+struct default_strategy<Box, Linear, box_tag, LinearTag, 2, 1,
+ spherical_equatorial_tag, spherical_equatorial_tag>
+{
+ typedef segment_box_spherical type;
+};
+
+} // namespace services
+
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}}}} // namespace boost::geometry::strategy::disjoint
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISJOINT_SEGMENT_BOX_HPP
+
diff --git a/boost/geometry/strategies/spherical/intersection.hpp b/boost/geometry/strategies/spherical/intersection.hpp
index 5d37583333..44b1cc62bf 100644
--- a/boost/geometry/strategies/spherical/intersection.hpp
+++ b/boost/geometry/strategies/spherical/intersection.hpp
@@ -41,6 +41,7 @@
#include <boost/geometry/strategies/side_info.hpp>
#include <boost/geometry/strategies/spherical/area.hpp>
#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
+#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>
#include <boost/geometry/strategies/within.hpp>
@@ -147,6 +148,14 @@ struct ecef_segments
return strategy_type();
}
+ typedef envelope::spherical_segment<CalculationType>
+ envelope_strategy_type;
+
+ static inline envelope_strategy_type get_envelope_strategy()
+ {
+ return envelope_strategy_type();
+ }
+
enum intersection_point_flag { ipi_inters = 0, ipi_at_a1, ipi_at_a2, ipi_at_b1, ipi_at_b2 };
// segment_intersection_info cannot outlive relate_ecef_segments
@@ -293,36 +302,64 @@ struct ecef_segments
vec3d_t const b1v = calc_policy.template to_cart3d<vec3d_t>(b1);
vec3d_t const b2v = calc_policy.template to_cart3d<vec3d_t>(b2);
+ bool degen_neq_coords = false;
side_info sides;
typename CalcPolicy::template plane<vec3d_t>
plane2 = calc_policy.get_plane(b1v, b2v);
- // not normalized normals, the same as in side strategy
- sides.set<0>(plane2.side_value(a1v), plane2.side_value(a2v));
- if (sides.same<0>())
+ calc_t dist_b1_b2 = 0;
+ if (! b_is_point)
{
- // Both points are at same side of other segment, we can leave
- return Policy::disjoint();
+ calculate_dist(b1v, b2v, plane2, dist_b1_b2);
+ if (math::equals(dist_b1_b2, c0))
+ {
+ degen_neq_coords = true;
+ b_is_point = true;
+ dist_b1_b2 = 0;
+ }
+ else
+ {
+ // not normalized normals, the same as in side strategy
+ sides.set<0>(plane2.side_value(a1v), plane2.side_value(a2v));
+ if (sides.same<0>())
+ {
+ // Both points are at same side of other segment, we can leave
+ return Policy::disjoint();
+ }
+ }
}
typename CalcPolicy::template plane<vec3d_t>
plane1 = calc_policy.get_plane(a1v, a2v);
- // not normalized normals, the same as in side strategy
- sides.set<1>(plane1.side_value(b1v), plane1.side_value(b2v));
- if (sides.same<1>())
+ calc_t dist_a1_a2 = 0;
+ if (! a_is_point)
{
- // Both points are at same side of other segment, we can leave
- return Policy::disjoint();
+ calculate_dist(a1v, a2v, plane1, dist_a1_a2);
+ if (math::equals(dist_a1_a2, c0))
+ {
+ degen_neq_coords = true;
+ a_is_point = true;
+ dist_a1_a2 = 0;
+ }
+ else
+ {
+ // not normalized normals, the same as in side strategy
+ sides.set<1>(plane1.side_value(b1v), plane1.side_value(b2v));
+ if (sides.same<1>())
+ {
+ // Both points are at same side of other segment, we can leave
+ return Policy::disjoint();
+ }
+ }
}
// NOTE: at this point the segments may still be disjoint
- calc_t len1, len2;
-
+ calc_t len1 = 0;
// point or opposite sides of a sphere/spheroid, assume point
- if (! detail::vec_normalize(plane1.normal, len1))
+ if (! a_is_point && ! detail::vec_normalize(plane1.normal, len1))
{
a_is_point = true;
if (sides.get<0, 0>() == 0 || sides.get<0, 1>() == 0)
@@ -331,7 +368,8 @@ struct ecef_segments
}
}
- if (! detail::vec_normalize(plane2.normal, len2))
+ calc_t len2 = 0;
+ if (! b_is_point && ! detail::vec_normalize(plane2.normal, len2))
{
b_is_point = true;
if (sides.get<1, 0>() == 0 || sides.get<1, 1>() == 0)
@@ -395,30 +433,32 @@ struct ecef_segments
{
if (a_is_point)
{
- return collinear_one_degenerated<Policy, calc_t>(a, true, b1, b2, a1, a2, b1v, b2v, plane2, a1v);
+ return collinear_one_degenerated<Policy, calc_t>(a, true, b1, b2, a1, a2, b1v, b2v,
+ plane2, a1v, a2v, dist_b1_b2, degen_neq_coords);
}
else if (b_is_point)
{
// b2 used to be consistent with (degenerated) checks above (is it needed?)
- return collinear_one_degenerated<Policy, calc_t>(b, false, a1, a2, b1, b2, a1v, a2v, plane1, b1v);
+ return collinear_one_degenerated<Policy, calc_t>(b, false, a1, a2, b1, b2, a1v, a2v,
+ plane1, b1v, b2v, dist_a1_a2, degen_neq_coords);
}
else
{
- calc_t dist_a1_a2, dist_a1_b1, dist_a1_b2;
- calc_t dist_b1_b2, dist_b1_a1, dist_b1_a2;
+ calc_t dist_a1_b1, dist_a1_b2;
+ calc_t dist_b1_a1, dist_b1_a2;
// use shorter segment
if (len1 <= len2)
{
- calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane1, b1v, dist_a1_a2, dist_a1_b1);
- calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane1, b2v, dist_a1_a2, dist_a1_b2);
+ calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane1, b1v, b2v, dist_a1_a2, dist_a1_b1);
+ calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane1, b2v, b1v, dist_a1_a2, dist_a1_b2);
dist_b1_b2 = dist_a1_b2 - dist_a1_b1;
dist_b1_a1 = -dist_a1_b1;
dist_b1_a2 = dist_a1_a2 - dist_a1_b1;
}
else
{
- calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, plane2, a1v, dist_b1_b2, dist_b1_a1);
- calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, plane2, a2v, dist_b1_b2, dist_b1_a2);
+ calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, plane2, a1v, a2v, dist_b1_b2, dist_b1_a1);
+ calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, plane2, a2v, a1v, dist_b1_b2, dist_b1_a2);
dist_a1_a2 = dist_b1_a2 - dist_b1_a1;
dist_a1_b1 = -dist_b1_a1;
dist_a1_b2 = dist_b1_b2 - dist_b1_a1;
@@ -478,10 +518,11 @@ struct ecef_segments
vec3d_t i1;
intersection_point_flag ip_flag;
- calc_t dist_a1_a2, dist_a1_i1, dist_b1_b2, dist_b1_i1;
+ calc_t dist_a1_i1, dist_b1_i1;
if (calculate_ip_data(a1, a2, b1, b2, a1v, a2v, b1v, b2v,
- plane1, plane2, calc_policy, sides,
- i1, dist_a1_a2, dist_a1_i1, dist_b1_b2, dist_b1_i1, ip_flag))
+ plane1, plane2, calc_policy,
+ sides, dist_a1_a2, dist_b1_b2,
+ i1, dist_a1_i1, dist_b1_i1, ip_flag))
{
// intersects
segment_intersection_info
@@ -511,12 +552,14 @@ private:
collinear_one_degenerated(Segment const& segment, bool degenerated_a,
Point1 const& a1, Point1 const& a2,
Point2 const& b1, Point2 const& b2,
- Vec3d const& v1, Vec3d const& v2,
+ Vec3d const& a1v, Vec3d const& a2v,
Plane const& plane,
- Vec3d const& vother)
+ Vec3d const& b1v, Vec3d const& b2v,
+ CalcT const& dist_1_2,
+ bool degen_neq_coords)
{
- CalcT dist_1_2, dist_1_o;
- return ! calculate_collinear_data(a1, a2, b1, b2, v1, v2, plane, vother, dist_1_2, dist_1_o)
+ CalcT dist_1_o;
+ return ! calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane, b1v, b2v, dist_1_2, dist_1_o, degen_neq_coords)
? Policy::disjoint()
: Policy::one_degenerate(segment, segment_ratio<CalcT>(dist_1_o, dist_1_2), degenerated_a);
}
@@ -527,11 +570,14 @@ private:
Vec3d const& a1v, // in
Vec3d const& a2v, // in
Plane const& plane1, // in
- Vec3d const& b1v_or_b2v, // in
- CalcT& dist_a1_a2, CalcT& dist_a1_i1) // out
+ Vec3d const& b1v, // in
+ Vec3d const& b2v, // in
+ CalcT const& dist_a1_a2, // in
+ CalcT& dist_a1_i1, // out
+ bool degen_neq_coords = false) // in
{
// calculate dist_a1_a2 and dist_a1_i1
- calculate_dists(a1v, a2v, plane1, b1v_or_b2v, dist_a1_a2, dist_a1_i1);
+ calculate_dist(a1v, a2v, plane1, b1v, dist_a1_i1);
// if i1 is close to a1 and b1 or b2 is equal to a1
if (is_endpoint_equal(dist_a1_i1, a1, b1, b2))
@@ -546,6 +592,26 @@ private:
return true;
}
+ // check the other endpoint of a very short segment near the pole
+ if (degen_neq_coords)
+ {
+ static CalcT const c0 = 0;
+
+ CalcT dist_a1_i2 = 0;
+ calculate_dist(a1v, a2v, plane1, b2v, dist_a1_i2);
+
+ if (math::equals(dist_a1_i2, c0))
+ {
+ dist_a1_i1 = 0;
+ return true;
+ }
+ else if (math::equals(dist_a1_a2 - dist_a1_i2, c0))
+ {
+ dist_a1_i1 = dist_a1_a2;
+ return true;
+ }
+ }
+
// or i1 is on b
return segment_ratio<CalcT>(dist_a1_i1, dist_a1_a2).on_segment();
}
@@ -559,15 +625,17 @@ private:
Plane const& plane2, // in
CalcPolicy const& calc_policy, // in
side_info const& sides, // in
- Vec3d & ip, // out
- CalcT& dist_a1_a2, CalcT& dist_a1_ip, // out
- CalcT& dist_b1_b2, CalcT& dist_b1_ip, // out
- intersection_point_flag& ip_flag) // out
+ CalcT const& dist_a1_a2, // in
+ CalcT const& dist_b1_b2, // in
+ Vec3d & ip, // out
+ CalcT& dist_a1_ip, // out
+ CalcT& dist_b1_ip, // out
+ intersection_point_flag& ip_flag) // out
{
Vec3d ip1, ip2;
calc_policy.intersection_points(plane1, plane2, ip1, ip2);
- calculate_dists(a1v, a2v, plane1, ip1, dist_a1_a2, dist_a1_ip);
+ calculate_dist(a1v, a2v, plane1, ip1, dist_a1_ip);
ip = ip1;
// choose the opposite side of the globe if the distance is shorter
@@ -593,7 +661,7 @@ private:
return false;
}
- calculate_dists(b1v, b2v, plane2, ip, dist_b1_b2, dist_b1_ip);
+ calculate_dist(b1v, b2v, plane2, ip, dist_b1_ip);
bool is_on_b = false, is_near_b1 = false, is_near_b2 = false;
if (! is_potentially_crossing(dist_b1_b2, dist_b1_ip, is_on_b, is_near_b1, is_near_b2))
@@ -692,20 +760,26 @@ private:
}
template <typename Vec3d, typename Plane, typename CalcT>
- static inline void calculate_dists(Vec3d const& a1v, // in
- Vec3d const& a2v, // in
- Plane const& plane1, // in
- Vec3d const& i1, // in
- CalcT& dist_a1_a2, // out
- CalcT& dist_a1_i1) // out
+ static inline void calculate_dist(Vec3d const& a1v, // in
+ Vec3d const& a2v, // in
+ Plane const& plane1, // in
+ CalcT& dist_a1_a2) // out
{
- //CalcT const c0 = 0;
- CalcT const c1 = 1;
- CalcT const c2 = 2;
- CalcT const c4 = 4;
-
- CalcT cos_a1_a2 = plane1.cos_angle_between(a1v, a2v);
+ static CalcT const c1 = 1;
+ CalcT const cos_a1_a2 = plane1.cos_angle_between(a1v, a2v);
dist_a1_a2 = -cos_a1_a2 + c1; // [1, -1] -> [0, 2] representing [0, pi]
+ }
+
+ template <typename Vec3d, typename Plane, typename CalcT>
+ static inline void calculate_dist(Vec3d const& a1v, // in
+ Vec3d const& /*a2v*/, // in
+ Plane const& plane1, // in
+ Vec3d const& i1, // in
+ CalcT& dist_a1_i1) // out
+ {
+ static CalcT const c1 = 1;
+ static CalcT const c2 = 2;
+ static CalcT const c4 = 4;
bool is_forward = true;
CalcT cos_a1_i1 = plane1.cos_angle_between(a1v, i1, is_forward);
@@ -719,7 +793,19 @@ private:
dist_a1_i1 += c4; // += 2pi
}
}
-
+ /*
+ template <typename Vec3d, typename Plane, typename CalcT>
+ static inline void calculate_dists(Vec3d const& a1v, // in
+ Vec3d const& a2v, // in
+ Plane const& plane1, // in
+ Vec3d const& i1, // in
+ CalcT& dist_a1_a2, // out
+ CalcT& dist_a1_i1) // out
+ {
+ calculate_dist(a1v, a2v, plane1, dist_a1_a2);
+ calculate_dist(a1v, a2v, plane1, i1, dist_a1_i1);
+ }
+ */
// the dist of the ip on the other side of the sphere
template <typename CalcT>
static inline CalcT dist_of_i2(CalcT const& dist_a1_i1)
@@ -760,8 +846,9 @@ private:
static inline bool is_endpoint_equal(CalcT const& dist,
P1 const& ai, P2 const& b1, P2 const& b2)
{
+ static CalcT const c0 = 0;
using geometry::detail::equals::equals_point_point;
- return is_near(dist) && (equals_point_point(ai, b1) || equals_point_point(ai, b2));
+ return is_near(dist) && (equals_point_point(ai, b1) || equals_point_point(ai, b2) || math::equals(dist, c0));
}
template <typename CalcT>
diff --git a/boost/geometry/strategies/spherical/ssf.hpp b/boost/geometry/strategies/spherical/ssf.hpp
index c99e5835e2..03f5428ede 100644
--- a/boost/geometry/strategies/spherical/ssf.hpp
+++ b/boost/geometry/strategies/spherical/ssf.hpp
@@ -23,6 +23,8 @@
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/strategies/side.hpp>
+#include <boost/geometry/strategies/spherical/disjoint_segment_box.hpp>
+#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
//#include <boost/geometry/strategies/concepts/side_concept.hpp>
@@ -82,6 +84,20 @@ class spherical_side_formula
{
public :
+ typedef strategy::envelope::spherical_segment<CalculationType> envelope_strategy_type;
+
+ static inline envelope_strategy_type get_envelope_strategy()
+ {
+ return envelope_strategy_type();
+ }
+
+ typedef strategy::disjoint::segment_box_spherical disjoint_strategy_type;
+
+ static inline disjoint_strategy_type get_disjoint_strategy()
+ {
+ return disjoint_strategy_type();
+ }
+
template <typename P1, typename P2, typename P>
static inline int apply(P1 const& p1, P2 const& p2, P const& p)
{
diff --git a/boost/geometry/strategies/strategies.hpp b/boost/geometry/strategies/strategies.hpp
index f3c6787a4b..27a025c7c4 100644
--- a/boost/geometry/strategies/strategies.hpp
+++ b/boost/geometry/strategies/strategies.hpp
@@ -69,6 +69,7 @@
#include <boost/geometry/strategies/spherical/area.hpp>
#include <boost/geometry/strategies/spherical/azimuth.hpp>
+#include <boost/geometry/strategies/spherical/disjoint_segment_box.hpp>
#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
#include <boost/geometry/strategies/spherical/distance_cross_track.hpp>
#include <boost/geometry/strategies/spherical/distance_cross_track_point_box.hpp>
@@ -79,6 +80,7 @@
#include <boost/geometry/strategies/geographic/area.hpp>
#include <boost/geometry/strategies/geographic/azimuth.hpp>
+#include <boost/geometry/strategies/geographic/disjoint_segment_box.hpp>
#include <boost/geometry/strategies/geographic/distance.hpp>
#include <boost/geometry/strategies/geographic/distance_andoyer.hpp>
#include <boost/geometry/strategies/geographic/distance_thomas.hpp>
diff --git a/boost/hana.hpp b/boost/hana.hpp
index 2e30810b1b..a8ad0413f1 100644
--- a/boost/hana.hpp
+++ b/boost/hana.hpp
@@ -114,6 +114,7 @@ namespace boost {
#include <boost/hana/greater.hpp>
#include <boost/hana/greater_equal.hpp>
#include <boost/hana/group.hpp>
+#include <boost/hana/index_if.hpp>
#include <boost/hana/if.hpp>
#include <boost/hana/insert.hpp>
#include <boost/hana/insert_range.hpp>
diff --git a/boost/hana/at_key.hpp b/boost/hana/at_key.hpp
index 74d45d6d56..e4f2e11255 100644
--- a/boost/hana/at_key.hpp
+++ b/boost/hana/at_key.hpp
@@ -3,6 +3,7 @@
Defines `boost::hana::at_key`.
@copyright Louis Dionne 2013-2017
+@copyright Jason Rice 2017
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
@@ -24,6 +25,7 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/find_if.hpp>
#include <boost/hana/first.hpp>
#include <boost/hana/functional/on.hpp>
+#include <boost/hana/index_if.hpp>
#include <boost/hana/length.hpp>
#include <boost/hana/optional.hpp>
#include <boost/hana/second.hpp>
@@ -67,42 +69,16 @@ BOOST_HANA_NAMESPACE_BEGIN
return hana::equal(t, u);
}
};
-
- //! @todo This causes an awful duplication of code with `find_if`.
- template <typename Xs, typename Pred, std::size_t i, std::size_t N, bool Done>
- struct advance_until;
-
- template <typename Xs, typename Pred, std::size_t i, std::size_t N>
- struct advance_until<Xs, Pred, i, N, false>
- : advance_until<Xs, Pred, i + 1, N, static_cast<bool>(detail::decay<decltype(
- std::declval<Pred>()(hana::at_c<i>(std::declval<Xs>()))
- )>::type::value)>
- { };
-
- template <typename Xs, typename Pred, std::size_t N>
- struct advance_until<Xs, Pred, N, N, false> {
- template <typename Ys>
- static constexpr auto apply(Ys&&) = delete;
- };
-
- template <typename Xs, typename Pred, std::size_t i, std::size_t N>
- struct advance_until<Xs, Pred, i, N, true> {
- template <typename Ys>
- static constexpr decltype(auto) apply(Ys&& ys) {
- return hana::at_c<i - 1>(static_cast<Ys&&>(ys));
- }
- };
}
template <typename S>
struct at_key_impl<S, when<hana::Sequence<S>::value>> {
template <typename Xs, typename Key>
- static constexpr decltype(auto) apply(Xs&& xs, Key const&) {
- constexpr std::size_t N = decltype(hana::length(xs))::value;
- using Pred = at_key_detail::equal_to<Key>;
- return at_key_detail::advance_until<Xs&&, Pred, 0, N, false>::apply(
- static_cast<Xs&&>(xs)
- );
+ static constexpr decltype(auto) apply(Xs&& xs, Key const& key) {
+ using Result = decltype(hana::index_if(
+ static_cast<Xs&&>(xs), at_key_detail::equal_to<Key>{key}));
+
+ return hana::at(static_cast<Xs&&>(xs), Result{}.value());
}
};
diff --git a/boost/hana/basic_tuple.hpp b/boost/hana/basic_tuple.hpp
index dbc762fb1b..3e624694e0 100644
--- a/boost/hana/basic_tuple.hpp
+++ b/boost/hana/basic_tuple.hpp
@@ -21,15 +21,12 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/fwd/core/make.hpp>
#include <boost/hana/fwd/core/tag_of.hpp>
#include <boost/hana/fwd/drop_front.hpp>
+#include <boost/hana/fwd/integral_constant.hpp>
#include <boost/hana/fwd/is_empty.hpp>
+#include <boost/hana/fwd/length.hpp>
#include <boost/hana/fwd/transform.hpp>
#include <boost/hana/fwd/unpack.hpp>
-#if 0 //! @todo Until we strip down headers, this includes too much
-#include <boost/hana/fwd/integral_constant.hpp>
-#include <boost/hana/fwd/length.hpp>
-#endif
-
#include <cstddef>
#include <type_traits>
#include <utility>
@@ -244,7 +241,6 @@ BOOST_HANA_NAMESPACE_BEGIN
}
};
-#if 0
//////////////////////////////////////////////////////////////////////////
// length
//////////////////////////////////////////////////////////////////////////
@@ -252,10 +248,9 @@ BOOST_HANA_NAMESPACE_BEGIN
struct length_impl<basic_tuple_tag> {
template <typename ...Xn>
static constexpr auto apply(basic_tuple<Xn...> const&) {
- return hana::size_c<sizeof...(Xn)>;
+ return hana::size_t<sizeof...(Xn)>{};
}
};
-#endif
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_BASIC_TUPLE_HPP
diff --git a/boost/hana/detail/index_if.hpp b/boost/hana/detail/index_if.hpp
index 8224f74be8..f643eb76ff 100644
--- a/boost/hana/detail/index_if.hpp
+++ b/boost/hana/detail/index_if.hpp
@@ -3,6 +3,7 @@
Defines `boost::hana::detail::index_if`.
@copyright Louis Dionne 2013-2017
+@copyright Jason Rice 2017
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
@@ -11,61 +12,44 @@ Distributed under the Boost Software License, Version 1.0.
#define BOOST_HANA_DETAIL_INDEX_IF_HPP
#include <boost/hana/config.hpp>
-#include <boost/hana/core/when.hpp>
+#include <boost/hana/detail/decay.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/optional.hpp>
#include <cstddef>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
- template <typename ...T>
- struct pack {
- static constexpr std::size_t length = sizeof...(T);
+ template <std::size_t i, std::size_t N, bool Done>
+ struct index_if_helper;
+
+ template <std::size_t i, std::size_t N>
+ struct index_if_helper<i, N, false> {
+ template <typename Pred, typename X1, typename ...Xs>
+ using f = typename index_if_helper<i + 1, N,
+ static_cast<bool>(detail::decay<decltype(
+ std::declval<Pred>()(std::declval<X1>()))>::type::value)
+ >::template f<Pred, Xs...>;
};
- template <typename T>
- struct make_pack;
-
- template <template <typename...> class Template, typename ...T>
- struct make_pack<Template<T...>> {
- using type = pack<T...>;
- };
-
- template <typename T> struct make_pack<T const> : make_pack<T> { };
- template <typename T> struct make_pack<T&> : make_pack<T> { };
- template <typename T> struct make_pack<T&&> : make_pack<T> { };
-
-
- //! @ingroup group-details
- //! Returns the index of the first element of the `pack<>` that satisfies
- //! the predicate, or the size of the pack if there is no such element.
- //!
- //! @note
- //! The predicate must return an `IntegralConstant` that can be explicitly
- //! converted to `bool`.
- template <typename Pred, typename Ts, typename = when<true>>
- struct index_if;
-
- //! @cond
- template <typename Pred, typename T, typename ...Ts>
- struct index_if<Pred, pack<T, Ts...>, when<static_cast<bool>(decltype(
- std::declval<Pred>()(std::declval<T>())
- )::value)>> {
- static constexpr std::size_t value = 0;
+ template <std::size_t N>
+ struct index_if_helper<N, N, false> {
+ template <typename ...>
+ using f = hana::optional<>;
};
- template <typename Pred, typename T, typename ...Ts>
- struct index_if<Pred, pack<T, Ts...>, when<!static_cast<bool>(decltype(
- std::declval<Pred>()(std::declval<T>())
- )::value)>> {
- static constexpr std::size_t value = 1 + index_if<Pred, pack<Ts...>>::value;
+ template <std::size_t i, std::size_t N>
+ struct index_if_helper<i, N, true> {
+ template <typename ...>
+ using f = hana::optional<hana::size_t<i - 1>>;
};
- template <typename Pred>
- struct index_if<Pred, pack<>> {
- static constexpr std::size_t value = 0;
+ template <typename Pred, typename ...Xs>
+ struct index_if {
+ using type = typename index_if_helper<0, sizeof...(Xs), false>
+ ::template f<Pred, Xs...>;
};
- //! @endcond
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_INDEX_IF_HPP
diff --git a/boost/hana/detail/struct_macros.erb.hpp b/boost/hana/detail/struct_macros.hpp.erb
index 2cdc419593..b3675e82af 100644
--- a/boost/hana/detail/struct_macros.erb.hpp
+++ b/boost/hana/detail/struct_macros.hpp.erb
@@ -5,7 +5,7 @@
be controlled with the 'MAX_NUMBER_OF_MEMBERS' variable,
which can be set when calling ERB to generate the header:
- export MAX_NUMBER_OF_MEMBERS=55; erb struct_macros.erb.hpp
+ export MAX_NUMBER_OF_MEMBERS=55; erb struct_macros.hpp.erb
'MAX_NUMBER_OF_MEMBERS' must be <= 62, otherwise an error is triggered.
In case 'MAX_NUMBER_OF_MEMBERS' is not specified, it defaults to 40.
diff --git a/boost/hana/detail/variadic/foldl1.hpp b/boost/hana/detail/variadic/foldl1.hpp
index 320755f7c7..31388028ab 100644
--- a/boost/hana/detail/variadic/foldl1.hpp
+++ b/boost/hana/detail/variadic/foldl1.hpp
@@ -15,6 +15,7 @@ Distributed under the Boost Software License, Version 1.0.
BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
+ //! @cond
template <unsigned int n, typename = when<true>>
struct foldl1_impl;
@@ -195,6 +196,7 @@ BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
, static_cast<Xn&&>(xn)...);
}
};
+ //! @endcond
struct foldl1_t {
template <typename F, typename X1, typename ...Xn>
diff --git a/boost/hana/detail/variadic/foldr1.hpp b/boost/hana/detail/variadic/foldr1.hpp
index 6221451d90..c7323cdaf8 100644
--- a/boost/hana/detail/variadic/foldr1.hpp
+++ b/boost/hana/detail/variadic/foldr1.hpp
@@ -15,6 +15,7 @@ Distributed under the Boost Software License, Version 1.0.
BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
+ //! @cond
template <unsigned int n, typename = when<true>>
struct foldr1_impl;
@@ -181,6 +182,7 @@ BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
foldr1_impl<sizeof...(xn) + 1>::apply(f, static_cast<X56&&>(x56), static_cast<Xn&&>(xn)...))))))))))))))))))))))))))))))))))))))))))))))))))))))));
}
};
+ //! @endcond
struct foldr1_t {
template <typename F, typename X1, typename ...Xn>
diff --git a/boost/hana/difference.hpp b/boost/hana/difference.hpp
index 158e727481..d2e2897d6e 100644
--- a/boost/hana/difference.hpp
+++ b/boost/hana/difference.hpp
@@ -14,6 +14,7 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/erase_key.hpp>
BOOST_HANA_NAMESPACE_BEGIN
diff --git a/boost/hana/experimental/view.hpp b/boost/hana/experimental/view.hpp
index e9a10b0820..cc2f4c606f 100644
--- a/boost/hana/experimental/view.hpp
+++ b/boost/hana/experimental/view.hpp
@@ -16,6 +16,7 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/detail/decay.hpp>
#include <boost/hana/fold_left.hpp>
#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/functional/on.hpp>
#include <boost/hana/fwd/ap.hpp>
#include <boost/hana/fwd/concat.hpp>
#include <boost/hana/fwd/drop_front.hpp>
diff --git a/boost/hana/ext/std/array.hpp b/boost/hana/ext/std/array.hpp
index 0cb513073c..59bc49cf8d 100644
--- a/boost/hana/ext/std/array.hpp
+++ b/boost/hana/ext/std/array.hpp
@@ -149,13 +149,21 @@ BOOST_HANA_NAMESPACE_BEGIN
//////////////////////////////////////////////////////////////////////////
template <>
struct less_impl<ext::std::array_tag, ext::std::array_tag> {
- template <typename T, typename U>
- static constexpr auto apply(std::array<T, 0> const&, std::array<U, 0> const&)
- { return hana::false_c; }
-
template <typename T, std::size_t n, typename U, std::size_t m>
static constexpr auto apply(std::array<T, n> const& xs, std::array<U, m> const& ys) {
- return detail::lexicographical_compare(&xs[0], &xs[0] + n, &ys[0], &ys[0] + m);
+ // This logic is more complex than it needs to be because we can't
+ // use `.begin()` and `.end()`, which are not constexpr in C++14,
+ // and because `&arr[0]` is UB when the array is empty.
+ if (xs.empty()) {
+ return !ys.empty();
+ } else {
+ if (ys.empty()) {
+ return false;
+ } else {
+ return detail::lexicographical_compare(&xs[0], &xs[0] + n,
+ &ys[0], &ys[0] + m);
+ }
+ }
}
};
BOOST_HANA_NAMESPACE_END
diff --git a/boost/hana/find_if.hpp b/boost/hana/find_if.hpp
index 3c4e07fcb0..de9c3d3eea 100644
--- a/boost/hana/find_if.hpp
+++ b/boost/hana/find_if.hpp
@@ -3,6 +3,7 @@
Defines `boost::hana::find_if`.
@copyright Louis Dionne 2013-2017
+@copyright Jason Rice 2017
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
@@ -17,19 +18,12 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/bool.hpp>
#include <boost/hana/concept/iterable.hpp>
#include <boost/hana/concept/searchable.hpp>
-#include <boost/hana/concept/sequence.hpp>
#include <boost/hana/concept/struct.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
-#include <boost/hana/detail/decay.hpp>
-#include <boost/hana/drop_while.hpp>
#include <boost/hana/first.hpp>
-#include <boost/hana/front.hpp>
#include <boost/hana/functional/compose.hpp>
-#include <boost/hana/is_empty.hpp>
-#include <boost/hana/length.hpp>
-#include <boost/hana/not.hpp>
-#include <boost/hana/optional.hpp>
+#include <boost/hana/index_if.hpp>
#include <boost/hana/second.hpp>
#include <boost/hana/transform.hpp>
@@ -62,68 +56,26 @@ BOOST_HANA_NAMESPACE_BEGIN
};
namespace detail {
- template <typename Xs, typename Pred, std::size_t i, std::size_t N, bool Done>
- struct advance_until;
-
- template <typename Xs, typename Pred, std::size_t i, std::size_t N>
- struct advance_until<Xs, Pred, i, N, false>
- : advance_until<Xs, Pred, i + 1, N, static_cast<bool>(detail::decay<decltype(
- std::declval<Pred>()(hana::at_c<i>(std::declval<Xs>()))
- )>::type::value)>
- { };
-
- template <typename Xs, typename Pred, std::size_t N>
- struct advance_until<Xs, Pred, N, N, false> {
- template <typename Ys>
- static constexpr auto apply(Ys&&) {
- return hana::nothing;
- }
- };
+ template <typename Xs>
+ struct partial_at {
+ Xs const& xs;
- template <typename Xs, typename Pred, std::size_t i, std::size_t N>
- struct advance_until<Xs, Pred, i, N, true> {
- template <typename Ys>
- static constexpr auto apply(Ys&& ys) {
- return hana::just(hana::at_c<i - 1>(static_cast<Ys&&>(ys)));
+ template <typename I>
+ constexpr decltype(auto) operator()(I i) const {
+ return hana::at(xs, i);
}
};
}
- template <typename S>
- struct find_if_impl<S, when<Sequence<S>::value>> {
- template <typename Xs, typename Pred>
- static constexpr auto apply(Xs&& xs, Pred&&) {
- constexpr std::size_t N = decltype(hana::length(xs))::value;
- return detail::advance_until<Xs&&, Pred&&, 0, N, false>::apply(
- static_cast<Xs&&>(xs)
- );
- }
- };
-
- template <typename It>
- struct find_if_impl<It, when<hana::Iterable<It>::value && !Sequence<It>::value>> {
- template <typename Xs, typename Pred>
- static constexpr auto find_if_helper(Xs&& xs, Pred&& pred, hana::true_) {
- return hana::just(hana::front(
- hana::drop_while(static_cast<Xs&&>(xs),
- hana::compose(hana::not_, static_cast<Pred&&>(pred)))
- ));
- }
-
- template <typename Xs, typename Pred>
- static constexpr auto find_if_helper(Xs&&, Pred&&, hana::false_) {
- return hana::nothing;
- }
-
+ template <typename Tag>
+ struct find_if_impl<Tag, when<Iterable<Tag>::value>> {
template <typename Xs, typename Pred>
static constexpr auto apply(Xs&& xs, Pred&& pred) {
- constexpr bool found = !decltype(
- hana::is_empty(hana::drop_while(static_cast<Xs&&>(xs),
- hana::compose(hana::not_, static_cast<Pred&&>(pred))))
- )::value;
- return find_if_impl::find_if_helper(static_cast<Xs&&>(xs),
- static_cast<Pred&&>(pred),
- hana::bool_<found>{});
+ using Result = decltype(hana::index_if(
+ static_cast<Xs&&>(xs), static_cast<Pred&&>(pred)));
+
+ return hana::transform(Result{},
+ detail::partial_at<std::decay_t<Xs>>{static_cast<Xs&&>(xs)});
}
};
diff --git a/boost/hana/fwd/adjust_if.hpp b/boost/hana/fwd/adjust_if.hpp
index 017ac03972..3042dc72c9 100644
--- a/boost/hana/fwd/adjust_if.hpp
+++ b/boost/hana/fwd/adjust_if.hpp
@@ -31,7 +31,7 @@ BOOST_HANA_NAMESPACE_BEGIN
//! ---------
//! Given a `Functor` `F` and a `Logical` `Bool`, the signature is
//! \f$
- //! \mathtt{adjust_if} : F(T) \times (T \to Bool) \times (T \to T) \to F(T)
+ //! \mathtt{adjust\_if} : F(T) \times (T \to Bool) \times (T \to T) \to F(T)
//! \f$
//!
//! @param xs
diff --git a/boost/hana/fwd/core/tag_of.hpp b/boost/hana/fwd/core/tag_of.hpp
index bcc4ef8e53..5d490dd717 100644
--- a/boost/hana/fwd/core/tag_of.hpp
+++ b/boost/hana/fwd/core/tag_of.hpp
@@ -57,7 +57,7 @@ BOOST_HANA_NAMESPACE_BEGIN
//! std::is_same<
//! typename fusion::traits::tag_of<T>::type,
//! fusion::traits::tag_of<fusion::vector<>>::type
- //! >{}
+ //! >::value
//! >> {
//! using type = BoostFusionVector;
//! };
diff --git a/boost/hana/fwd/difference.hpp b/boost/hana/fwd/difference.hpp
index 3702f075e0..d96142b5b9 100644
--- a/boost/hana/fwd/difference.hpp
+++ b/boost/hana/fwd/difference.hpp
@@ -15,50 +15,18 @@ Distributed under the Boost Software License, Version 1.0.
BOOST_HANA_NAMESPACE_BEGIN
- //! Returns the set-theoretic difference of two sets.
- //! @relates hana::set
- //!
- //! Given two sets `xs` and `ys`, `difference(xs, ys)` is a new set
- //! containing all the elements of `xs` that are _not_ contained in `ys`.
- //! For any object `x`, the following holds:
- //! @code
- //! x ^in^ difference(xs, ys) if and only if x ^in^ xs && !(x ^in^ ys)
- //! @endcode
- //!
- //!
- //! @note
- //! This operation is not commutative, i.e. `difference(xs, ys)` is not
- //! necessarily the same as `difference(ys, xs)`. Indeed, consider the
- //! case where `xs` is empty and `ys` isn't. Then, `difference(xs, ys)`
- //! is empty but `difference(ys, xs)` is equal to `ys`. For the symmetric
- //! version of this operation, see `symmetric_difference`.
- //!
- //!
- //! @param xs
- //! A set to remove values from.
- //!
- //! @param ys
- //! The set whose values are removed from `xs`.
- //!
- //!
- //! Example
- //! -------
- //! @include example/difference.cpp
-#ifdef BOOST_HANA_DOXYGEN_INVOKED
- constexpr auto difference = [](auto&& xs, auto&& ys) {
- return tag-dispatched;
- };
-#else
+ // Note: This function is documented per datatype/concept only.
+ //! @cond
template <typename S, typename = void>
struct difference_impl : difference_impl<S, when<true>> { };
+ //! @endcond
struct difference_t {
template <typename Xs, typename Ys>
- constexpr auto operator()(Xs&& xs, Ys&& ys) const;
+ constexpr auto operator()(Xs&&, Ys&&) const;
};
constexpr difference_t difference{};
-#endif
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_FWD_DIFFERENCE_HPP
diff --git a/boost/hana/fwd/index_if.hpp b/boost/hana/fwd/index_if.hpp
new file mode 100644
index 0000000000..59f98f59fa
--- /dev/null
+++ b/boost/hana/fwd/index_if.hpp
@@ -0,0 +1,60 @@
+/*!
+@file
+Forward declares `boost::hana::index_if`.
+
+@copyright Louis Dionne 2013-2017
+@copyright Jason Rice 2017
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_INDEX_IF_HPP
+#define BOOST_HANA_FWD_INDEX_IF_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Finds the value associated to the first key satisfying a predicate.
+ //! @ingroup group-Iterable
+ //!
+ //! Given an `Iterable` structure `xs` and a predicate `pred`,
+ //! `index_if(xs, pred)` returns a `hana::optional` containing an `IntegralConstant`
+ //! of the index of the first element that satisfies the predicate or nothing
+ //! if no element satisfies the predicate.
+ //!
+ //!
+ //! @param xs
+ //! The structure to be searched.
+ //!
+ //! @param predicate
+ //! A function called as `predicate(x)`, where `x` is an element of the
+ //! `Iterable` structure and returning whether `x` is the element being
+ //! searched for. In the current version of the library, the predicate
+ //! has to return an `IntegralConstant` holding a value that can be
+ //! converted to `bool`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/index_if.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto index_if = [](auto&& xs, auto&& predicate) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct index_if_impl : index_if_impl<S, when<true>> { };
+
+ struct index_if_t {
+ template <typename Xs, typename Pred>
+ constexpr auto operator()(Xs&& xs, Pred&& pred) const;
+ };
+
+ constexpr index_if_t index_if{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_INDEX_IF_HPP
+
diff --git a/boost/hana/fwd/intersection.hpp b/boost/hana/fwd/intersection.hpp
index ec9b1daad2..f289dd03fa 100644
--- a/boost/hana/fwd/intersection.hpp
+++ b/boost/hana/fwd/intersection.hpp
@@ -15,39 +15,18 @@ Distributed under the Boost Software License, Version 1.0.
BOOST_HANA_NAMESPACE_BEGIN
- //! Returns the intersection of two sets.
- //! @relates hana::set
- //!
- //! Given two sets `xs` and `ys`, `intersection(xs, ys)` is a new set
- //! containing exactly those elements that are present both in `xs` and
- //! in `ys`. In other words, the following holds for any object `x`:
- //! @code
- //! x ^in^ intersection(xs, ys) if and only if x ^in^ xs && x ^in^ ys
- //! @endcode
- //!
- //!
- //! @param xs, ys
- //! Two sets to intersect.
- //!
- //!
- //! Example
- //! -------
- //! @include example/intersection.cpp
-#ifdef BOOST_HANA_DOXYGEN_INVOKED
- constexpr auto intersection = [](auto&& xs, auto&& ys) {
- return tag-dispatched;
- };
-#else
+ // Note: This function is documented per datatype/concept only.
+ //! @cond
template <typename S, typename = void>
struct intersection_impl : intersection_impl<S, when<true>> { };
+ //! @endcond
struct intersection_t {
template <typename Xs, typename Ys>
- constexpr auto operator()(Xs&& xs, Ys&& ys) const;
+ constexpr auto operator()(Xs&&, Ys&&) const;
};
constexpr intersection_t intersection{};
-#endif
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_FWD_INTERSECTION_HPP
diff --git a/boost/hana/fwd/map.hpp b/boost/hana/fwd/map.hpp
index bff0b012f0..c00f57195f 100644
--- a/boost/hana/fwd/map.hpp
+++ b/boost/hana/fwd/map.hpp
@@ -255,6 +255,126 @@ BOOST_HANA_NAMESPACE_BEGIN
return tag-dispatched;
};
#endif
+
+ //! Returns the union of two maps.
+ //! @relates hana::map
+ //!
+ //! Given two maps `xs` and `ys`, `hana::union_(xs, ys)` is a new map
+ //! containing all the elements of `xs` and all the elements of `ys`,
+ //! without duplicates. If both `xs` and `ys` contain an element with the
+ //! same `key`, the one in `ys` is taken. Functionally,
+ //! `hana::union_(xs, ys)` is equivalent to
+ //! @code
+ //! hana::fold_left(xs, ys, hana::insert)
+ //! @endcode
+ //!
+ //! @param xs, ys
+ //! The two maps to compute the union of.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/map/union.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto union_ = [](auto&& xs, auto&& ys) {
+ return tag-dispatched;
+ };
+#endif
+
+ //! Returns the intersection of two maps.
+ //! @relates hana::map
+ //!
+ //! Given two maps `xs` and `ys`, `intersection(xs, ys)` is a new map
+ //! containing exactly those (key, value) pairs from xs, for which key
+ //! is present in `ys`.
+ //! In other words, the following holds for any object `pair(k, v)`:
+ //! @code
+ //! pair(k, v) ^in^ intersection(xs, ys) if and only if (k, v) ^in^ xs && k ^in^ keys(ys)
+ //! @endcode
+ //!
+ //!
+ //! @note
+ //! This function is not commutative, i.e. `intersection(xs, ys)` is not
+ //! necessarily the same as `intersection(ys, xs)`. Indeed, the set of keys
+ //! in `intersection(xs, ys)` is always the same as the set of keys in
+ //! `intersection(ys, xs)`, but the value associated to each key may be
+ //! different. `intersection(xs, ys)` contains values present in `xs`, and
+ //! `intersection(ys, xs)` contains values present in `ys`.
+ //!
+ //!
+ //! @param xs, ys
+ //! Two maps to intersect.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/map/intersection.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto intersection = [](auto&& xs, auto&& ys) {
+ return tag-dispatched;
+ };
+#endif
+
+ //! Returns the difference of two maps.
+ //! @relates hana::map
+ //!
+ //! Given two maps `xs` and `ys`, `difference(xs, ys)` is a new map
+ //! containing exactly those (key, value) pairs from xs, for which key
+ //! is not present in `keys(ys)`.
+ //! In other words, the following holds for any object `pair(k, v)`:
+ //! @code
+ //! pair(k, v) ^in^ difference(xs, ys) if and only if (k, v) ^in^ xs && k ^not in^ keys(ys)
+ //! @endcode
+ //!
+ //!
+ //! @note
+ //! This function is not commutative, i.e. `difference(xs, ys)` is not
+ //! necessarily the same as `difference(ys, xs)`.
+ //! Indeed, consider the case where `xs` is empty and `ys` isn't.
+ //! In that case, `difference(xs, ys)` is empty, but `difference(ys, xs)`
+ //! is equal to `ys`.
+ //! For symmetric version of this operation, see `symmetric_difference`.
+ //!
+ //!
+ //! @param xs, ys
+ //! Two maps to compute the difference of.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/map/intersection.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto difference = [](auto&& xs, auto&& ys) {
+ return tag-dispatched;
+ };
+#endif
+
+ //! Returns the symmetric set-theoretic difference of two maps.
+ //! @relates hana::map
+ //!
+ //! Given two sets `xs` and `ys`, `symmetric_difference(xs, ys)` is a new
+ //! map containing all the elements of `xs` whose keys are not contained in `keys(ys)`,
+ //! and all the elements of `ys` whose keys are not contained in `keys(xs)`. The
+ //! symmetric difference of two maps satisfies the following:
+ //! @code
+ //! symmetric_difference(xs, ys) == union_(difference(xs, ys), difference(ys, xs))
+ //! @endcode
+ //!
+ //!
+ //! @param xs, ys
+ //! Two maps to compute the symmetric difference of.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/map/symmetric_difference.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+constexpr auto symmetric_difference = [](auto&& xs, auto&& ys) {
+ return tag-dispatched;
+ };
+#endif
+
+
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_FWD_MAP_HPP
diff --git a/boost/hana/fwd/replace_if.hpp b/boost/hana/fwd/replace_if.hpp
index e3fe882125..48d5b4c15c 100644
--- a/boost/hana/fwd/replace_if.hpp
+++ b/boost/hana/fwd/replace_if.hpp
@@ -24,7 +24,7 @@ BOOST_HANA_NAMESPACE_BEGIN
//! ---------
//! Given `F` a Functor and `Bool` a Logical, the signature is
//! \f$
- //! \mathtt{replace_if} : F(T) \times (T \to Bool) \times T \to F(T)
+ //! \mathtt{replace\_if} : F(T) \times (T \to Bool) \times T \to F(T)
//! \f$
//!
//! @param xs
diff --git a/boost/hana/fwd/set.hpp b/boost/hana/fwd/set.hpp
index 55bd72d248..7312854782 100644
--- a/boost/hana/fwd/set.hpp
+++ b/boost/hana/fwd/set.hpp
@@ -182,9 +182,116 @@ BOOST_HANA_NAMESPACE_BEGIN
};
#endif
+ //! Returns the union of two sets.
+ //! @relates hana::set
+ //!
+ //! Given two sets `xs` and `ys`, `union_(xs, ys)` is a new set containing
+ //! all the elements of `xs` and all the elements of `ys`, without
+ //! duplicates. For any object `x`, the following holds: `x` is in
+ //! `hana::union_(xs, ys)` if and only if `x` is in `xs` or `x` is in `ys`.
+ //!
+ //!
+ //! @param xs, ys
+ //! Two sets to compute the union of.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/set/union.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto union_ = [](auto&& xs, auto&& ys) {
+ return tag-dispatched;
+ };
+#endif
+
+ //! Returns the intersection of two sets.
+ //! @relates hana::set
+ //!
+ //! Given two sets `xs` and `ys`, `intersection(xs, ys)` is a new set
+ //! containing exactly those elements that are present both in `xs` and
+ //! in `ys`.
+ //! In other words, the following holds for any object `x`:
+ //! @code
+ //! x ^in^ intersection(xs, ys) if and only if x ^in^ xs && x ^in^ ys
+ //! @endcode
+ //!
+ //!
+ //! @param xs, ys
+ //! Two sets to intersect.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/set/intersection.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto intersection = [](auto&& xs, auto&& ys) {
+ return tag-dispatched;
+ };
+#endif
//! Equivalent to `to<set_tag>`; provided for convenience.
//! @relates hana::set
constexpr auto to_set = to<set_tag>;
+
+ //! Returns the set-theoretic difference of two sets.
+ //! @relates hana::set
+ //!
+ //! Given two sets `xs` and `ys`, `difference(xs, ys)` is a new set
+ //! containing all the elements of `xs` that are _not_ contained in `ys`.
+ //! For any object `x`, the following holds:
+ //! @code
+ //! x ^in^ difference(xs, ys) if and only if x ^in^ xs && !(x ^in^ ys)
+ //! @endcode
+ //!
+ //!
+ //! This operation is not commutative, i.e. `difference(xs, ys)` is not
+ //! necessarily the same as `difference(ys, xs)`. Indeed, consider the
+ //! case where `xs` is empty and `ys` isn't. Then, `difference(xs, ys)`
+ //! is empty but `difference(ys, xs)` is equal to `ys`. For the symmetric
+ //! version of this operation, see `symmetric_difference`.
+ //!
+ //!
+ //! @param xs
+ //! A set param to remove values from.
+ //!
+ //! @param ys
+ //! The set whose values are removed from `xs`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/set/difference.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto difference = [](auto&& xs, auto&& ys) {
+ return tag-dispatched;
+};
+#endif
+
+ //! Returns the symmetric set-theoretic difference of two sets.
+ //! @relates hana::set
+ //!
+ //! Given two sets `xs` and `ys`, `symmetric_difference(xs, ys)` is a new
+ //! set containing all the elements of `xs` that are not contained in `ys`,
+ //! and all the elements of `ys` that are not contained in `xs`. The
+ //! symmetric difference of two sets satisfies the following:
+ //! @code
+ //! symmetric_difference(xs, ys) == union_(difference(xs, ys), difference(ys, xs))
+ //! @endcode
+ //!
+ //!
+ //! @param xs, ys
+ //! Two sets to compute the symmetric difference of.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/set/symmetric_difference.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+constexpr auto symmetric_difference = [](auto&& xs, auto&& ys) {
+ return tag-dispatched;
+ };
+#endif
+
+
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_FWD_SET_HPP
diff --git a/boost/hana/fwd/symmetric_difference.hpp b/boost/hana/fwd/symmetric_difference.hpp
index 2908daaeee..2253f167eb 100644
--- a/boost/hana/fwd/symmetric_difference.hpp
+++ b/boost/hana/fwd/symmetric_difference.hpp
@@ -15,40 +15,18 @@ Distributed under the Boost Software License, Version 1.0.
BOOST_HANA_NAMESPACE_BEGIN
- //! Returns the symmetric set-theoretic difference of two sets.
- //! @relates hana::set
- //!
- //! Given two sets `xs` and `ys`, `symmetric_difference(xs, ys)` is a new
- //! set containing all the elements of `xs` that are not contained in `ys`,
- //! and all the elements of `ys` that are not contained in `xs`. The
- //! symmetric difference of two sets satisfies the following:
- //! @code
- //! symmetric_difference(xs, ys) == union_(difference(xs, ys), difference(ys, xs))
- //! @endcode
- //!
- //!
- //! @param xs, ys
- //! Two sets to compute the symmetric difference of.
- //!
- //!
- //! Example
- //! -------
- //! @include example/symmetric_difference.cpp
-#ifdef BOOST_HANA_DOXYGEN_INVOKED
- constexpr auto symmetric_difference = [](auto&& xs, auto&& ys) {
- return tag-dispatched;
- };
-#else
+ // Note: This function is documented per datatype/concept only.
+ //! @cond
template <typename S, typename = void>
struct symmetric_difference_impl : symmetric_difference_impl<S, when<true>> { };
+ //! @endcond
struct symmetric_difference_t {
template <typename Xs, typename Ys>
- constexpr auto operator()(Xs&& xs, Ys&& ys) const;
+ constexpr auto operator()(Xs&&, Ys&&) const;
};
constexpr symmetric_difference_t symmetric_difference{};
-#endif
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_FWD_SYMMETRIC_DIFFERENCE_HPP
diff --git a/boost/hana/fwd/union.hpp b/boost/hana/fwd/union.hpp
index ccf539221f..5775151888 100644
--- a/boost/hana/fwd/union.hpp
+++ b/boost/hana/fwd/union.hpp
@@ -15,39 +15,18 @@ Distributed under the Boost Software License, Version 1.0.
BOOST_HANA_NAMESPACE_BEGIN
- //! Returns the union of two sets.
- //! @relates hana::set
- //!
- //! Given two sets `xs` and `ys`, `union_(xs, ys)` is a new set containing
- //! all the elements of `xs` and all the elements of `ys`, without
- //! duplicates. For any object `x`, the following holds:
- //! @code
- //! x ^in^ union_(xs, ys) if and only if x ^in^ xs || x ^in^ ys
- //! @endcode
- //!
- //!
- //! @param xs, ys
- //! Two sets to compute the union of.
- //!
- //!
- //! Example
- //! -------
- //! @include example/union.cpp
-#ifdef BOOST_HANA_DOXYGEN_INVOKED
- constexpr auto union_ = [](auto&& xs, auto&& ys) {
- return tag-dispatched;
- };
-#else
- template <typename S, typename = void>
- struct union_impl : union_impl<S, when<true>> { };
+ // Note: This function is documented per datatype/concept only.
+ //! @cond
+ template <typename T, typename = void>
+ struct union_impl : union_impl<T, when<true>> { };
+ //! @endcond
struct union_t {
template <typename Xs, typename Ys>
- constexpr auto operator()(Xs&& xs, Ys&& ys) const;
+ constexpr auto operator()(Xs&&, Ys&&) const;
};
constexpr union_t union_{};
-#endif
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_FWD_UNION_HPP
diff --git a/boost/hana/index_if.hpp b/boost/hana/index_if.hpp
new file mode 100644
index 0000000000..93ec21c75c
--- /dev/null
+++ b/boost/hana/index_if.hpp
@@ -0,0 +1,105 @@
+/*!
+@file
+Defines `boost::hana::index_if`.
+
+@copyright Louis Dionne 2013-2017
+@copyright Jason Rice 2017
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_INDEX_IF_HPP
+#define BOOST_HANA_INDEX_IF_HPP
+
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/concept/iterable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/decay.hpp>
+#include <boost/hana/detail/index_if.hpp>
+#include <boost/hana/fwd/at.hpp>
+#include <boost/hana/fwd/basic_tuple.hpp>
+#include <boost/hana/fwd/index_if.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/optional.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Pred>
+ constexpr auto index_if_t::operator()(Xs&& xs, Pred&& pred) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using IndexIf = BOOST_HANA_DISPATCH_IF(index_if_impl<S>,
+ hana::Iterable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Iterable<S>::value,
+ "hana::index_if(xs, pred) requires 'xs' to be a Iterable");
+ #endif
+
+ return IndexIf::apply(static_cast<Xs&&>(xs), static_cast<Pred&&>(pred));
+ }
+ //! @endcond
+
+ namespace detail {
+ template <std::size_t i, std::size_t N, bool Done>
+ struct iterate_while;
+
+ template <std::size_t i, std::size_t N>
+ struct iterate_while<i, N, false> {
+ template <typename Xs, typename Pred>
+ using f = typename iterate_while<i + 1, N,
+ static_cast<bool>(detail::decay<decltype(
+ std::declval<Pred>()(
+ hana::at(std::declval<Xs>(), hana::size_c<i>)))>::type::value)
+ >::template f<Xs, Pred>;
+ };
+
+ template <std::size_t N>
+ struct iterate_while<N, N, false> {
+ template <typename Xs, typename Pred>
+ using f = hana::optional<>;
+ };
+
+ template <std::size_t i, std::size_t N>
+ struct iterate_while<i, N, true> {
+ template <typename Xs, typename Pred>
+ using f = hana::optional<hana::size_t<i - 1>>;
+ };
+ }
+
+ template <typename Tag>
+ struct index_if_impl<Tag, when<Foldable<Tag>::value>> {
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs const& xs, Pred const&)
+ -> typename detail::iterate_while<0,
+ decltype(hana::length(xs))::value, false>
+ ::template f<Xs, Pred>
+ { return {}; }
+ };
+
+ template <typename It>
+ struct index_if_impl<It, when<!Foldable<It>::value>> {
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs const&, Pred const&)
+ -> typename detail::iterate_while<hana::size_c<0>,
+ static_cast<std::size_t>(-1), false>
+ ::template f<Xs, Pred>
+ { return {}; }
+ };
+
+ // basic_tuple is implemented here to solve circular dependency issues.
+ template <>
+ struct index_if_impl<basic_tuple_tag> {
+ template <typename ...Xs, typename Pred>
+ static constexpr auto apply(basic_tuple<Xs...> const&, Pred const&)
+ -> typename detail::index_if<Pred, Xs...>::type
+ { return {}; }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_INDEX_IF_HPP
diff --git a/boost/hana/map.hpp b/boost/hana/map.hpp
index cccf6cf3b9..8da5012190 100644
--- a/boost/hana/map.hpp
+++ b/boost/hana/map.hpp
@@ -40,9 +40,12 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/functional/partial.hpp>
#include <boost/hana/fwd/any_of.hpp>
#include <boost/hana/fwd/at_key.hpp>
+#include <boost/hana/fwd/difference.hpp>
#include <boost/hana/fwd/erase_key.hpp>
+#include <boost/hana/fwd/intersection.hpp>
#include <boost/hana/fwd/is_subset.hpp>
#include <boost/hana/fwd/keys.hpp>
+#include <boost/hana/fwd/union.hpp>
#include <boost/hana/insert.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/keys.hpp>
@@ -53,6 +56,7 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/unpack.hpp>
#include <boost/hana/value.hpp>
+
#include <cstddef>
#include <type_traits>
#include <utility>
@@ -480,6 +484,71 @@ BOOST_HANA_NAMESPACE_BEGIN
};
//////////////////////////////////////////////////////////////////////////
+ // union_
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct union_impl<map_tag> {
+ template <typename Xs, typename Ys>
+ static constexpr auto apply(Xs&& xs, Ys&& ys) {
+ return hana::fold_left(static_cast<Xs&&>(xs), static_cast<Ys&&>(ys),
+ hana::insert);
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // intersection_
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <typename Ys>
+ struct map_insert_if_contains {
+ Ys const& ys;
+
+ // Second template param will be pair
+ // Get its key and check if it exists, if it does, insert key, value pair.
+ template <typename Result, typename Pair>
+ static constexpr auto helper(Result&& result, Pair&& pair, hana::true_) {
+ return hana::insert(static_cast<Result&&>(result), static_cast<Pair&&>(pair));
+ }
+
+ template <typename Result, typename Pair>
+ static constexpr auto helper(Result&& result, Pair&&, hana::false_) {
+ return static_cast<Result&&>(result);
+ }
+
+ template <typename Result, typename Pair>
+ constexpr auto operator()(Result&& result, Pair&& pair) const {
+ constexpr bool keep = hana::value<decltype(hana::contains(ys, hana::first(pair)))>();
+ return map_insert_if_contains::helper(static_cast<Result&&>(result),
+ static_cast<Pair&&>(pair),
+ hana::bool_c<keep>);
+ }
+ };
+ }
+
+ template <>
+ struct intersection_impl<map_tag> {
+ template <typename Xs, typename Ys>
+ static constexpr auto apply(Xs&& xs, Ys const& ys) {
+ return hana::fold_left(static_cast<Xs&&>(xs), hana::make_map(),
+ detail::map_insert_if_contains<Ys>{ys});
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // difference
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct difference_impl<map_tag> {
+ template <typename Xs, typename Ys>
+ static constexpr auto apply(Xs&& xs, Ys&& ys) {
+ return hana::fold_left(
+ hana::keys(static_cast<Ys&&>(ys)),
+ static_cast<Xs&&>(xs),
+ hana::erase_key);
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
// Foldable
//////////////////////////////////////////////////////////////////////////
template <>
diff --git a/boost/hana/pair.hpp b/boost/hana/pair.hpp
index 75cd9e287b..35ff857269 100644
--- a/boost/hana/pair.hpp
+++ b/boost/hana/pair.hpp
@@ -79,8 +79,8 @@ BOOST_HANA_NAMESPACE_BEGIN
BOOST_HANA_TT_IS_CONVERTIBLE(U const&, Second)
>::type>
constexpr pair(pair<T, U> const& other)
- : detail::ebo<detail::pix<0>, First>(detail::ebo_get<detail::pix<0>>(other))
- , detail::ebo<detail::pix<1>, Second>(detail::ebo_get<detail::pix<1>>(other))
+ : detail::ebo<detail::pix<0>, First>(hana::first(other))
+ , detail::ebo<detail::pix<1>, Second>(hana::second(other))
{ }
template <typename T, typename U, typename = typename std::enable_if<
@@ -90,8 +90,8 @@ BOOST_HANA_NAMESPACE_BEGIN
BOOST_HANA_TT_IS_CONVERTIBLE(U&&, Second)
>::type>
constexpr pair(pair<T, U>&& other)
- : detail::ebo<detail::pix<0>, First>(static_cast<T&&>(detail::ebo_get<detail::pix<0>>(other)))
- , detail::ebo<detail::pix<1>, Second>(static_cast<U&&>(detail::ebo_get<detail::pix<1>>(other)))
+ : detail::ebo<detail::pix<0>, First>(hana::first(static_cast<pair<T, U>&&>(other)))
+ , detail::ebo<detail::pix<1>, Second>(hana::second(static_cast<pair<T, U>&&>(other)))
{ }
@@ -101,8 +101,8 @@ BOOST_HANA_NAMESPACE_BEGIN
BOOST_HANA_TT_IS_ASSIGNABLE(Second&, U const&)
>::type>
constexpr pair& operator=(pair<T, U> const& other) {
- detail::ebo_get<detail::pix<0>>(*this) = detail::ebo_get<detail::pix<0>>(other);
- detail::ebo_get<detail::pix<1>>(*this) = detail::ebo_get<detail::pix<1>>(other);
+ hana::first(*this) = hana::first(other);
+ hana::second(*this) = hana::second(other);
return *this;
}
@@ -111,8 +111,8 @@ BOOST_HANA_NAMESPACE_BEGIN
BOOST_HANA_TT_IS_ASSIGNABLE(Second&, U&&)
>::type>
constexpr pair& operator=(pair<T, U>&& other) {
- detail::ebo_get<detail::pix<0>>(*this) = static_cast<T&&>(detail::ebo_get<detail::pix<0>>(other));
- detail::ebo_get<detail::pix<1>>(*this) = static_cast<U&&>(detail::ebo_get<detail::pix<1>>(other));
+ hana::first(*this) = hana::first(static_cast<pair<T, U>&&>(other));
+ hana::second(*this) = hana::second(static_cast<pair<T, U>&&>(other));
return *this;
}
diff --git a/boost/hana/tuple.hpp b/boost/hana/tuple.hpp
index cab5eaa4d6..3354a84bee 100644
--- a/boost/hana/tuple.hpp
+++ b/boost/hana/tuple.hpp
@@ -3,6 +3,7 @@
Defines `boost::hana::tuple`.
@copyright Louis Dionne 2013-2017
+@copyright Jason Rice 2017
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
@@ -27,7 +28,7 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/fwd/at.hpp>
#include <boost/hana/fwd/core/make.hpp>
#include <boost/hana/fwd/drop_front.hpp>
-#include <boost/hana/fwd/find_if.hpp>
+#include <boost/hana/fwd/index_if.hpp>
#include <boost/hana/fwd/is_empty.hpp>
#include <boost/hana/fwd/length.hpp>
#include <boost/hana/fwd/optional.hpp>
@@ -140,7 +141,7 @@ BOOST_HANA_NAMESPACE_BEGIN
// The three following constructors are required to make sure that
// the tuple(Yn&&...) constructor is _not_ preferred over the copy
// constructor for unary tuples containing a type that is constructible
- // from tuple<...>. See test/tuple/trap_construct.cpp
+ // from tuple<...>. See test/tuple/cnstr.trap.cpp
template <typename ...dummy, typename = typename std::enable_if<
detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn const&, dummy...)...>::value
>::type>
@@ -283,6 +284,14 @@ BOOST_HANA_NAMESPACE_BEGIN
return hana::at_c<n>(static_cast<tuple<Xs...>&&>(xs).storage_);
}
+ template <>
+ struct index_if_impl<tuple_tag> {
+ template <typename ...Xs, typename Pred>
+ static constexpr auto apply(tuple<Xs...> const&, Pred const&)
+ -> typename detail::index_if<Pred, Xs...>::type
+ { return {}; }
+ };
+
//////////////////////////////////////////////////////////////////////////
// Sequence
//////////////////////////////////////////////////////////////////////////
@@ -298,27 +307,6 @@ BOOST_HANA_NAMESPACE_BEGIN
tuple<typename detail::decay<Xs>::type...> apply(Xs&& ...xs)
{ return {static_cast<Xs&&>(xs)...}; }
};
-
- template <>
- struct find_if_impl<tuple_tag> {
- template <std::size_t index, typename Xs>
- static constexpr auto helper(Xs&&, hana::true_) {
- return hana::nothing;
- }
-
- template <std::size_t index, typename Xs>
- static constexpr auto helper(Xs&& xs, hana::false_) {
- return hana::just(hana::at_c<index>(static_cast<Xs&&>(xs)));
- }
-
- template <typename Xs, typename Pred>
- static constexpr auto apply(Xs&& xs, Pred&&) {
- using Pack = typename detail::make_pack<Xs>::type;
- constexpr std::size_t index = detail::index_if<Pred&&, Pack>::value;
- constexpr std::size_t len = Pack::length;
- return helper<index>(static_cast<Xs&&>(xs), hana::bool_c<index == len>);
- }
- };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_TUPLE_HPP
diff --git a/boost/hana/version.hpp b/boost/hana/version.hpp
index 2699bfd0e5..160170a51f 100644
--- a/boost/hana/version.hpp
+++ b/boost/hana/version.hpp
@@ -24,7 +24,7 @@ Distributed under the Boost Software License, Version 1.0.
//! @ingroup group-config
//! Macro expanding to the minor version of the library, i.e. the `y` in `x.y.z`.
-#define BOOST_HANA_MINOR_VERSION 1
+#define BOOST_HANA_MINOR_VERSION 2
//! @ingroup group-config
//! Macro expanding to the patch level of the library, i.e. the `z` in `x.y.z`.
diff --git a/boost/integer/common_factor_rt.hpp b/boost/integer/common_factor_rt.hpp
index c2b54db8e8..341b316501 100644
--- a/boost/integer/common_factor_rt.hpp
+++ b/boost/integer/common_factor_rt.hpp
@@ -1,454 +1,572 @@
-// Boost common_factor_rt.hpp header file ----------------------------------//
+// (C) Copyright Jeremy William Murphy 2016.
-// (C) Copyright Daryle Walker and Paul Moore 2001-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.
-
-// boostinspect:nolicense (don't complain about the lack of a Boost license)
-// (Paul Moore hasn't been in contact for years, so there's no way to change the
-// license.)
-
-// See http://www.boost.org for updates, documentation, and revision history.
+// 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_INTEGER_COMMON_FACTOR_RT_HPP
#define BOOST_INTEGER_COMMON_FACTOR_RT_HPP
-#include <boost/integer_fwd.hpp> // self include
+#include <boost/assert.hpp>
+#include <boost/core/enable_if.hpp>
#include <boost/config.hpp> // for BOOST_NESTED_TEMPLATE, etc.
#include <boost/limits.hpp> // for std::numeric_limits
#include <climits> // for CHAR_MIN
#include <boost/detail/workaround.hpp>
+#include <iterator>
+#include <algorithm>
+#include <limits>
+#ifndef BOOST_NO_CXX11_HDR_TYPE_TRAITS
+#include <type_traits>
+#endif
+#ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL
+#include <functional>
+#endif
+
+#if ((defined(BOOST_MSVC) && (BOOST_MSVC >= 1600)) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
+#include <intrin.h>
+#endif
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4127 4244) // Conditional expression is constant
#endif
-namespace boost
-{
-namespace integer
-{
-
-
-// Forward declarations for function templates -----------------------------//
-
-template < typename IntegerType >
- IntegerType gcd( IntegerType const &a, IntegerType const &b );
-
-template < typename IntegerType >
- IntegerType lcm( IntegerType const &a, IntegerType const &b );
-
-
-// Greatest common divisor evaluator class declaration ---------------------//
-
-template < typename IntegerType >
-class gcd_evaluator
-{
-public:
- // Types
- typedef IntegerType result_type, first_argument_type, second_argument_type;
-
- // Function object interface
- result_type operator ()( first_argument_type const &a,
- second_argument_type const &b ) const;
-
-}; // boost::integer::gcd_evaluator
-
-
-// Least common multiple evaluator class declaration -----------------------//
-
-template < typename IntegerType >
-class lcm_evaluator
-{
-public:
- // Types
- typedef IntegerType result_type, first_argument_type, second_argument_type;
-
- // Function object interface
- result_type operator ()( first_argument_type const &a,
- second_argument_type const &b ) const;
-
-}; // boost::integer::lcm_evaluator
-
-
-// Implementation details --------------------------------------------------//
-
-namespace detail
-{
- // Greatest common divisor for rings (including unsigned integers)
- template < typename RingType >
- RingType
- gcd_euclidean
- (
- RingType a,
- RingType b
- )
- {
- // Avoid repeated construction
- #ifndef __BORLANDC__
- RingType const zero = static_cast<RingType>( 0 );
- #else
- RingType zero = static_cast<RingType>( 0 );
- #endif
-
- // Reduce by GCD-remainder property [GCD(a,b) == GCD(b,a MOD b)]
- while ( true )
- {
- if ( a == zero )
- return b;
- b %= a;
-
- if ( b == zero )
- return a;
- a %= b;
- }
- }
-
- // Greatest common divisor for (signed) integers
- template < typename IntegerType >
- inline
- IntegerType
- gcd_integer
- (
- IntegerType const & a,
- IntegerType const & b
- )
- {
- // Avoid repeated construction
- IntegerType const zero = static_cast<IntegerType>( 0 );
- IntegerType const result = gcd_euclidean( a, b );
-
- return ( result < zero ) ? static_cast<IntegerType>(-result) : result;
- }
-
- // Greatest common divisor for unsigned binary integers
- template < typename BuiltInUnsigned >
- BuiltInUnsigned
- gcd_binary
- (
- BuiltInUnsigned u,
- BuiltInUnsigned v
- )
- {
- if ( u && v )
- {
- // Shift out common factors of 2
- unsigned shifts = 0;
-
- while ( !(u & 1u) && !(v & 1u) )
- {
- ++shifts;
- u >>= 1;
- v >>= 1;
- }
+#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_NO_CXX11_NOEXCEPT)
+#define BOOST_GCD_NOEXCEPT(T) noexcept(std::is_arithmetic<T>::value)
+#else
+#define BOOST_GCD_NOEXCEPT(T)
+#endif
- // Start with the still-even one, if any
- BuiltInUnsigned r[] = { u, v };
- unsigned which = static_cast<bool>( u & 1u );
+namespace boost {
+
+ template <class I>
+ class rational;
+
+ namespace integer {
+
+ namespace gcd_detail{
+
+ //
+ // some helper functions which really should be constexpr already, but sadly aren't:
+ //
+#ifndef BOOST_NO_CXX14_CONSTEXPR
+ template <class T>
+ inline constexpr T constexpr_min(T const& a, T const& b) BOOST_GCD_NOEXCEPT(T)
+ {
+ return a < b ? a : b;
+ }
+ template <class T>
+ inline constexpr auto constexpr_swap(T&a, T& b) BOOST_GCD_NOEXCEPT(T) -> decltype(a.swap(b))
+ {
+ return a.swap(b);
+ }
+ template <class T, class U>
+ inline constexpr void constexpr_swap(T&a, U& b...) BOOST_GCD_NOEXCEPT(T)
+ {
+ T t(static_cast<T&&>(a));
+ a = static_cast<T&&>(b);
+ b = static_cast<T&&>(t);
+ }
+#else
+ template <class T>
+ inline T constexpr_min(T const& a, T const& b) BOOST_GCD_NOEXCEPT(T)
+ {
+ return a < b ? a : b;
+ }
+ template <class T>
+ inline void constexpr_swap(T&a, T& b) BOOST_GCD_NOEXCEPT(T)
+ {
+ using std::swap;
+ swap(a, b);
+ }
+#endif
- // Whittle down the values via their differences
- do
+ template <class T, bool a =
+#ifndef BOOST_NO_CXX11_HDR_TYPE_TRAITS
+ std::is_unsigned<T>::value ||
+#endif
+ (std::numeric_limits<T>::is_specialized && !std::numeric_limits<T>::is_signed)>
+ struct gcd_traits_abs_defaults
+ {
+ inline static BOOST_CXX14_CONSTEXPR const T& abs(const T& val) BOOST_GCD_NOEXCEPT(T) { return val; }
+ };
+ template <class T>
+ struct gcd_traits_abs_defaults<T, false>
+ {
+ inline static T BOOST_CXX14_CONSTEXPR abs(const T& val) BOOST_GCD_NOEXCEPT(T)
+ {
+ // This sucks, but std::abs is not constexpr :(
+ return val < T(0) ? -val : val;
+ }
+ };
+
+ enum method_type
+ {
+ method_euclid = 0,
+ method_binary = 1,
+ method_mixed = 2
+ };
+
+ struct any_convert
+ {
+ template <class T>
+ any_convert(const T&);
+ };
+
+ struct unlikely_size
+ {
+ char buf[9973];
+ };
+
+ unlikely_size operator <<= (any_convert, any_convert);
+ unlikely_size operator >>= (any_convert, any_convert);
+
+ template <class T>
+ struct gcd_traits_defaults : public gcd_traits_abs_defaults<T>
+ {
+ BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(T& val) BOOST_GCD_NOEXCEPT(T)
+ {
+ unsigned r = 0;
+ while(0 == (val & 1u))
{
-#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
- while ( !(r[ which ] & 1u) )
- {
- r[ which ] = (r[which] >> 1);
- }
+#ifdef _MSC_VER // VC++ can't handle operator >>= in constexpr code for some reason
+ val = val >> 1;
#else
- // Remove factors of two from the even one
- while ( !(r[ which ] & 1u) )
- {
- r[ which ] >>= 1;
- }
+ val >>= 1;
#endif
-
- // Replace the larger of the two with their difference
- if ( r[!which] > r[which] )
- {
- which ^= 1u;
- }
-
- r[ which ] -= r[ !which ];
+ ++r;
}
- while ( r[which] );
-
- // Shift-in the common factor of 2 to the residues' GCD
- return r[ !which ] << shifts;
- }
- else
- {
- // At least one input is zero, return the other
- // (adding since zero is the additive identity)
- // or zero if both are zero.
- return u + v;
- }
- }
-
- // Least common multiple for rings (including unsigned integers)
- template < typename RingType >
- inline
- RingType
- lcm_euclidean
- (
- RingType const & a,
- RingType const & b
- )
- {
- RingType const zero = static_cast<RingType>( 0 );
- RingType const temp = gcd_euclidean( a, b );
-
- return ( temp != zero ) ? ( a / temp * b ) : zero;
- }
-
- // Least common multiple for (signed) integers
- template < typename IntegerType >
- inline
- IntegerType
- lcm_integer
- (
- IntegerType const & a,
- IntegerType const & b
- )
- {
- // Avoid repeated construction
- IntegerType const zero = static_cast<IntegerType>( 0 );
- IntegerType const result = lcm_euclidean( a, b );
-
- return ( result < zero ) ? static_cast<IntegerType>(-result) : result;
- }
-
- // Function objects to find the best way of computing GCD or LCM
-#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- template < typename T, bool IsSpecialized, bool IsSigned >
- struct gcd_optimal_evaluator_helper_t
- {
- T operator ()( T const &a, T const &b )
- {
- return gcd_euclidean( a, b );
- }
- };
-
- template < typename T >
- struct gcd_optimal_evaluator_helper_t< T, true, true >
- {
- T operator ()( T const &a, T const &b )
- {
- return gcd_integer( a, b );
- }
- };
-
- template < typename T >
- struct gcd_optimal_evaluator
- {
- T operator ()( T const &a, T const &b )
- {
- typedef ::std::numeric_limits<T> limits_type;
-
- typedef gcd_optimal_evaluator_helper_t<T,
- limits_type::is_specialized, limits_type::is_signed> helper_type;
-
- helper_type solver;
-
- return solver( a, b );
- }
- };
-#else // BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- template < typename T >
- struct gcd_optimal_evaluator
- {
- T operator ()( T const &a, T const &b )
- {
- return gcd_integer( a, b );
- }
- };
+ return r;
+ }
+ inline static BOOST_CXX14_CONSTEXPR bool less(const T& a, const T& b) BOOST_GCD_NOEXCEPT(T)
+ {
+ return a < b;
+ }
+
+ static T& get_value();
+
+#ifndef BOOST_NO_SFINAE
+ static const bool has_operator_left_shift_equal = sizeof(get_value() <<= 2) != sizeof(unlikely_size);
+ static const bool has_operator_right_shift_equal = sizeof(get_value() >>= 2) != sizeof(unlikely_size);
+#else
+ static const bool has_operator_left_shift_equal = true;
+ static const bool has_operator_right_shift_equal = true;
#endif
-
- // Specialize for the built-in integers
-#define BOOST_PRIVATE_GCD_UF( Ut ) \
- template < > struct gcd_optimal_evaluator<Ut> \
- { Ut operator ()( Ut a, Ut b ) const { return gcd_binary( a, b ); } }
-
- BOOST_PRIVATE_GCD_UF( unsigned char );
- BOOST_PRIVATE_GCD_UF( unsigned short );
- BOOST_PRIVATE_GCD_UF( unsigned );
- BOOST_PRIVATE_GCD_UF( unsigned long );
-
-#ifdef BOOST_HAS_LONG_LONG
- BOOST_PRIVATE_GCD_UF( boost::ulong_long_type );
-#elif defined(BOOST_HAS_MS_INT64)
- BOOST_PRIVATE_GCD_UF( unsigned __int64 );
+ static const method_type method = std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::is_integer && has_operator_left_shift_equal && has_operator_right_shift_equal ? method_mixed : method_euclid;
+ };
+ //
+ // Default gcd_traits just inherits from defaults:
+ //
+ template <class T>
+ struct gcd_traits : public gcd_traits_defaults<T> {};
+
+ //
+ // Some platforms have fast bitscan operations, that allow us to implement
+ // make_odd much more efficiently, unfortunately we can't use these if we want
+ // the functions to be constexpr as the compiler intrinsics aren't constexpr.
+ //
+#if defined(BOOST_NO_CXX14_CONSTEXPR) && ((defined(BOOST_MSVC) && (BOOST_MSVC >= 1600)) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
+#pragma intrinsic(_BitScanForward,)
+ template <>
+ struct gcd_traits<unsigned long> : public gcd_traits_defaults<unsigned long>
+ {
+ BOOST_FORCEINLINE static unsigned find_lsb(unsigned long val) BOOST_NOEXCEPT
+ {
+ unsigned long result;
+ _BitScanForward(&result, val);
+ return result;
+ }
+ BOOST_FORCEINLINE static unsigned make_odd(unsigned long& val) BOOST_NOEXCEPT
+ {
+ unsigned result = find_lsb(val);
+ val >>= result;
+ return result;
+ }
+ };
+
+#ifdef _M_X64
+#pragma intrinsic(_BitScanForward64)
+ template <>
+ struct gcd_traits<unsigned __int64> : public gcd_traits_defaults<unsigned __int64>
+ {
+ BOOST_FORCEINLINE static unsigned find_lsb(unsigned __int64 mask) BOOST_NOEXCEPT
+ {
+ unsigned long result;
+ _BitScanForward64(&result, mask);
+ return result;
+ }
+ BOOST_FORCEINLINE static unsigned make_odd(unsigned __int64& val) BOOST_NOEXCEPT
+ {
+ unsigned result = find_lsb(val);
+ val >>= result;
+ return result;
+ }
+ };
#endif
-
-#if CHAR_MIN == 0
- BOOST_PRIVATE_GCD_UF( char ); // char is unsigned
+ //
+ // Other integer type are trivial adaptations of the above,
+ // this works for signed types too, as by the time these functions
+ // are called, all values are > 0.
+ //
+ template <> struct gcd_traits<long> : public gcd_traits_defaults<long>
+ { BOOST_FORCEINLINE static unsigned make_odd(long& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
+ template <> struct gcd_traits<unsigned int> : public gcd_traits_defaults<unsigned int>
+ { BOOST_FORCEINLINE static unsigned make_odd(unsigned int& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
+ template <> struct gcd_traits<int> : public gcd_traits_defaults<int>
+ { BOOST_FORCEINLINE static unsigned make_odd(int& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
+ template <> struct gcd_traits<unsigned short> : public gcd_traits_defaults<unsigned short>
+ { BOOST_FORCEINLINE static unsigned make_odd(unsigned short& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
+ template <> struct gcd_traits<short> : public gcd_traits_defaults<short>
+ { BOOST_FORCEINLINE static unsigned make_odd(short& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
+ template <> struct gcd_traits<unsigned char> : public gcd_traits_defaults<unsigned char>
+ { BOOST_FORCEINLINE static unsigned make_odd(unsigned char& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
+ template <> struct gcd_traits<signed char> : public gcd_traits_defaults<signed char>
+ { BOOST_FORCEINLINE static signed make_odd(signed char& val)BOOST_NOEXCEPT{ signed result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
+ template <> struct gcd_traits<char> : public gcd_traits_defaults<char>
+ { BOOST_FORCEINLINE static unsigned make_odd(char& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
+#ifndef BOOST_NO_INTRINSIC_WCHAR_T
+ template <> struct gcd_traits<wchar_t> : public gcd_traits_defaults<wchar_t>
+ { BOOST_FORCEINLINE static unsigned make_odd(wchar_t& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
#endif
-
-#undef BOOST_PRIVATE_GCD_UF
-
-#define BOOST_PRIVATE_GCD_SF( St, Ut ) \
- template < > struct gcd_optimal_evaluator<St> \
- { St operator ()( St a, St b ) const { Ut const a_abs = \
- static_cast<Ut>( a < 0 ? -a : +a ), b_abs = static_cast<Ut>( \
- b < 0 ? -b : +b ); return static_cast<St>( \
- gcd_optimal_evaluator<Ut>()(a_abs, b_abs) ); } }
-
- BOOST_PRIVATE_GCD_SF( signed char, unsigned char );
- BOOST_PRIVATE_GCD_SF( short, unsigned short );
- BOOST_PRIVATE_GCD_SF( int, unsigned );
- BOOST_PRIVATE_GCD_SF( long, unsigned long );
-
-#if CHAR_MIN < 0
- BOOST_PRIVATE_GCD_SF( char, unsigned char ); // char is signed
+#ifdef _M_X64
+ template <> struct gcd_traits<__int64> : public gcd_traits_defaults<__int64>
+ { BOOST_FORCEINLINE static unsigned make_odd(__int64& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits<unsigned __int64>::find_lsb(val); val >>= result; return result; } };
#endif
-#ifdef BOOST_HAS_LONG_LONG
- BOOST_PRIVATE_GCD_SF( boost::long_long_type, boost::ulong_long_type );
-#elif defined(BOOST_HAS_MS_INT64)
- BOOST_PRIVATE_GCD_SF( __int64, unsigned __int64 );
+#elif defined(BOOST_GCC) || defined(__clang__) || (defined(BOOST_INTEL) && defined(__GNUC__))
+
+ template <>
+ struct gcd_traits<unsigned> : public gcd_traits_defaults<unsigned>
+ {
+ BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned find_lsb(unsigned mask)BOOST_NOEXCEPT
+ {
+ return __builtin_ctz(mask);
+ }
+ BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(unsigned& val)BOOST_NOEXCEPT
+ {
+ unsigned result = find_lsb(val);
+ val >>= result;
+ return result;
+ }
+ };
+ template <>
+ struct gcd_traits<unsigned long> : public gcd_traits_defaults<unsigned long>
+ {
+ BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned find_lsb(unsigned long mask)BOOST_NOEXCEPT
+ {
+ return __builtin_ctzl(mask);
+ }
+ BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(unsigned long& val)BOOST_NOEXCEPT
+ {
+ unsigned result = find_lsb(val);
+ val >>= result;
+ return result;
+ }
+ };
+ template <>
+ struct gcd_traits<boost::ulong_long_type> : public gcd_traits_defaults<boost::ulong_long_type>
+ {
+ BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned find_lsb(boost::ulong_long_type mask)BOOST_NOEXCEPT
+ {
+ return __builtin_ctzll(mask);
+ }
+ BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(boost::ulong_long_type& val)BOOST_NOEXCEPT
+ {
+ unsigned result = find_lsb(val);
+ val >>= result;
+ return result;
+ }
+ };
+ //
+ // Other integer type are trivial adaptations of the above,
+ // this works for signed types too, as by the time these functions
+ // are called, all values are > 0.
+ //
+ template <> struct gcd_traits<boost::long_long_type> : public gcd_traits_defaults<boost::long_long_type>
+ {
+ BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(boost::long_long_type& val)BOOST_NOEXCEPT { unsigned result = gcd_traits<boost::ulong_long_type>::find_lsb(val); val >>= result; return result; }
+ };
+ template <> struct gcd_traits<long> : public gcd_traits_defaults<long>
+ {
+ BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(long& val)BOOST_NOEXCEPT { unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; }
+ };
+ template <> struct gcd_traits<int> : public gcd_traits_defaults<int>
+ {
+ BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(int& val)BOOST_NOEXCEPT { unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; }
+ };
+ template <> struct gcd_traits<unsigned short> : public gcd_traits_defaults<unsigned short>
+ {
+ BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(unsigned short& val)BOOST_NOEXCEPT { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
+ };
+ template <> struct gcd_traits<short> : public gcd_traits_defaults<short>
+ {
+ BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(short& val)BOOST_NOEXCEPT { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
+ };
+ template <> struct gcd_traits<unsigned char> : public gcd_traits_defaults<unsigned char>
+ {
+ BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(unsigned char& val)BOOST_NOEXCEPT { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
+ };
+ template <> struct gcd_traits<signed char> : public gcd_traits_defaults<signed char>
+ {
+ BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR signed make_odd(signed char& val)BOOST_NOEXCEPT { signed result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
+ };
+ template <> struct gcd_traits<char> : public gcd_traits_defaults<char>
+ {
+ BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(char& val)BOOST_NOEXCEPT { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
+ };
+#ifndef BOOST_NO_INTRINSIC_WCHAR_T
+ template <> struct gcd_traits<wchar_t> : public gcd_traits_defaults<wchar_t>
+ {
+ BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(wchar_t& val)BOOST_NOEXCEPT { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
+ };
#endif
-
-#undef BOOST_PRIVATE_GCD_SF
-
-#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- template < typename T, bool IsSpecialized, bool IsSigned >
- struct lcm_optimal_evaluator_helper_t
+#endif
+ //
+ // The Mixed Binary Euclid Algorithm
+ // Sidi Mohamed Sedjelmaci
+ // Electronic Notes in Discrete Mathematics 35 (2009) 169-176
+ //
+ template <class T>
+ BOOST_CXX14_CONSTEXPR T mixed_binary_gcd(T u, T v) BOOST_GCD_NOEXCEPT(T)
+ {
+ if(gcd_traits<T>::less(u, v))
+ constexpr_swap(u, v);
+
+ unsigned shifts = 0;
+
+ if(u == T(0))
+ return v;
+ if(v == T(0))
+ return u;
+
+ shifts = constexpr_min(gcd_traits<T>::make_odd(u), gcd_traits<T>::make_odd(v));
+
+ while(gcd_traits<T>::less(1, v))
+ {
+ u %= v;
+ v -= u;
+ if(u == T(0))
+ return v << shifts;
+ if(v == T(0))
+ return u << shifts;
+ gcd_traits<T>::make_odd(u);
+ gcd_traits<T>::make_odd(v);
+ if(gcd_traits<T>::less(u, v))
+ constexpr_swap(u, v);
+ }
+ return (v == 1 ? v : u) << shifts;
+ }
+
+ /** Stein gcd (aka 'binary gcd')
+ *
+ * From Mathematics to Generic Programming, Alexander Stepanov, Daniel Rose
+ */
+ template <typename SteinDomain>
+ BOOST_CXX14_CONSTEXPR SteinDomain Stein_gcd(SteinDomain m, SteinDomain n) BOOST_GCD_NOEXCEPT(SteinDomain)
{
- T operator ()( T const &a, T const &b )
+ BOOST_ASSERT(m >= 0);
+ BOOST_ASSERT(n >= 0);
+ if (m == SteinDomain(0))
+ return n;
+ if (n == SteinDomain(0))
+ return m;
+ // m > 0 && n > 0
+ int d_m = gcd_traits<SteinDomain>::make_odd(m);
+ int d_n = gcd_traits<SteinDomain>::make_odd(n);
+ // odd(m) && odd(n)
+ while (m != n)
{
- return lcm_euclidean( a, b );
+ if (n > m)
+ constexpr_swap(n, m);
+ m -= n;
+ gcd_traits<SteinDomain>::make_odd(m);
}
- };
+ // m == n
+ m <<= constexpr_min(d_m, d_n);
+ return m;
+ }
- template < typename T >
- struct lcm_optimal_evaluator_helper_t< T, true, true >
+
+ /** Euclidean algorithm
+ *
+ * From Mathematics to Generic Programming, Alexander Stepanov, Daniel Rose
+ *
+ */
+ template <typename EuclideanDomain>
+ inline BOOST_CXX14_CONSTEXPR EuclideanDomain Euclid_gcd(EuclideanDomain a, EuclideanDomain b) BOOST_GCD_NOEXCEPT(EuclideanDomain)
{
- T operator ()( T const &a, T const &b )
+ while (b != EuclideanDomain(0))
{
- return lcm_integer( a, b );
+ a %= b;
+ constexpr_swap(a, b);
}
- };
-
- template < typename T >
- struct lcm_optimal_evaluator
- {
- T operator ()( T const &a, T const &b )
- {
- typedef ::std::numeric_limits<T> limits_type;
-
- typedef lcm_optimal_evaluator_helper_t<T,
- limits_type::is_specialized, limits_type::is_signed> helper_type;
+ return a;
+ }
- helper_type solver;
- return solver( a, b );
- }
- };
-#else // BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- template < typename T >
- struct lcm_optimal_evaluator
+ template <typename T>
+ inline BOOST_CXX14_CONSTEXPR BOOST_DEDUCED_TYPENAME enable_if_c<gcd_traits<T>::method == method_mixed, T>::type
+ optimal_gcd_select(T const &a, T const &b) BOOST_GCD_NOEXCEPT(T)
{
- T operator ()( T const &a, T const &b )
- {
- return lcm_integer( a, b );
- }
- };
-#endif
+ return gcd_detail::mixed_binary_gcd(a, b);
+ }
- // Functions to find the GCD or LCM in the best way
- template < typename T >
- inline
- T
- gcd_optimal
- (
- T const & a,
- T const & b
- )
+ template <typename T>
+ inline BOOST_CXX14_CONSTEXPR BOOST_DEDUCED_TYPENAME enable_if_c<gcd_traits<T>::method == method_binary, T>::type
+ optimal_gcd_select(T const &a, T const &b) BOOST_GCD_NOEXCEPT(T)
{
- gcd_optimal_evaluator<T> solver;
-
- return solver( a, b );
+ return gcd_detail::Stein_gcd(a, b);
}
- template < typename T >
- inline
- T
- lcm_optimal
- (
- T const & a,
- T const & b
- )
+ template <typename T>
+ inline BOOST_CXX14_CONSTEXPR BOOST_DEDUCED_TYPENAME enable_if_c<gcd_traits<T>::method == method_euclid, T>::type
+ optimal_gcd_select(T const &a, T const &b) BOOST_GCD_NOEXCEPT(T)
{
- lcm_optimal_evaluator<T> solver;
-
- return solver( a, b );
+ return gcd_detail::Euclid_gcd(a, b);
}
-} // namespace detail
+ template <class T>
+ inline BOOST_CXX14_CONSTEXPR T lcm_imp(const T& a, const T& b) BOOST_GCD_NOEXCEPT(T)
+ {
+ T temp = boost::integer::gcd_detail::optimal_gcd_select(a, b);
+#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40500)
+ return (temp != T(0)) ? T(a / temp * b) : T(0);
+#else
+ return temp != T(0) ? T(a / temp * b) : T(0);
+#endif
+ }
+} // namespace detail
-// Greatest common divisor evaluator member function definition ------------//
-template < typename IntegerType >
-inline
-typename gcd_evaluator<IntegerType>::result_type
-gcd_evaluator<IntegerType>::operator ()
-(
- first_argument_type const & a,
- second_argument_type const & b
-) const
+template <typename Integer>
+inline BOOST_CXX14_CONSTEXPR Integer gcd(Integer const &a, Integer const &b) BOOST_GCD_NOEXCEPT(Integer)
{
- return detail::gcd_optimal( a, b );
+ if(a == (std::numeric_limits<Integer>::min)())
+ return a == static_cast<Integer>(0) ? gcd_detail::gcd_traits<Integer>::abs(b) : boost::integer::gcd(static_cast<Integer>(a % b), b);
+ else if (b == (std::numeric_limits<Integer>::min)())
+ return b == static_cast<Integer>(0) ? gcd_detail::gcd_traits<Integer>::abs(a) : boost::integer::gcd(a, static_cast<Integer>(b % a));
+ return gcd_detail::optimal_gcd_select(static_cast<Integer>(gcd_detail::gcd_traits<Integer>::abs(a)), static_cast<Integer>(gcd_detail::gcd_traits<Integer>::abs(b)));
}
-
-// Least common multiple evaluator member function definition --------------//
-
-template < typename IntegerType >
-inline
-typename lcm_evaluator<IntegerType>::result_type
-lcm_evaluator<IntegerType>::operator ()
-(
- first_argument_type const & a,
- second_argument_type const & b
-) const
+template <typename Integer>
+inline BOOST_CXX14_CONSTEXPR Integer lcm(Integer const &a, Integer const &b) BOOST_GCD_NOEXCEPT(Integer)
{
- return detail::lcm_optimal( a, b );
+ return gcd_detail::lcm_imp(static_cast<Integer>(gcd_detail::gcd_traits<Integer>::abs(a)), static_cast<Integer>(gcd_detail::gcd_traits<Integer>::abs(b)));
+}
+#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+//
+// This looks slightly odd, but the variadic forms must have 3 or more arguments, and the variadic argument pack may be empty.
+// This matters not at all for most compilers, but Oracle C++ selects the wrong overload in the 2-arg case unless we do this.
+//
+template <typename Integer, typename... Args>
+inline BOOST_CXX14_CONSTEXPR Integer gcd(Integer const &a, Integer const &b, const Integer& c, Args const&... args) BOOST_GCD_NOEXCEPT(Integer)
+{
+ Integer t = gcd(b, c, args...);
+ return t == 1 ? 1 : gcd(a, t);
}
-
-// Greatest common divisor and least common multiple function definitions --//
-
-template < typename IntegerType >
-inline
-IntegerType
-gcd
-(
- IntegerType const & a,
- IntegerType const & b
-)
+template <typename Integer, typename... Args>
+inline BOOST_CXX14_CONSTEXPR Integer lcm(Integer const &a, Integer const &b, Integer const& c, Args const&... args) BOOST_GCD_NOEXCEPT(Integer)
{
- gcd_evaluator<IntegerType> solver;
+ return lcm(a, lcm(b, c, args...));
+}
+#endif
+//
+// Special handling for rationals:
+//
+template <typename Integer>
+inline typename boost::enable_if_c<std::numeric_limits<Integer>::is_specialized, boost::rational<Integer> >::type gcd(boost::rational<Integer> const &a, boost::rational<Integer> const &b)
+{
+ return boost::rational<Integer>(static_cast<Integer>(gcd(a.numerator(), b.numerator())), static_cast<Integer>(lcm(a.denominator(), b.denominator())));
+}
- return solver( a, b );
+template <typename Integer>
+inline typename boost::enable_if_c<std::numeric_limits<Integer>::is_specialized, boost::rational<Integer> >::type lcm(boost::rational<Integer> const &a, boost::rational<Integer> const &b)
+{
+ return boost::rational<Integer>(static_cast<Integer>(lcm(a.numerator(), b.numerator())), static_cast<Integer>(gcd(a.denominator(), b.denominator())));
+}
+/**
+ * Knuth, The Art of Computer Programming: Volume 2, Third edition, 1998
+ * Chapter 4.5.2, Algorithm C: Greatest common divisor of n integers.
+ *
+ * Knuth counts down from n to zero but we naturally go from first to last.
+ * We also return the termination position because it might be useful to know.
+ *
+ * Partly by quirk, partly by design, this algorithm is defined for n = 1,
+ * because the gcd of {x} is x. It is not defined for n = 0.
+ *
+ * @tparam I Input iterator.
+ * @return The gcd of the range and the iterator position at termination.
+ */
+template <typename I>
+std::pair<typename std::iterator_traits<I>::value_type, I>
+gcd_range(I first, I last) BOOST_GCD_NOEXCEPT(I)
+{
+ BOOST_ASSERT(first != last);
+ typedef typename std::iterator_traits<I>::value_type T;
+
+ T d = *first++;
+ while (d != T(1) && first != last)
+ {
+ d = gcd(d, *first);
+ first++;
+ }
+ return std::make_pair(d, first);
+}
+template <typename I>
+std::pair<typename std::iterator_traits<I>::value_type, I>
+lcm_range(I first, I last) BOOST_GCD_NOEXCEPT(I)
+{
+ BOOST_ASSERT(first != last);
+ typedef typename std::iterator_traits<I>::value_type T;
+
+ T d = *first++;
+ while (d != T(1) && first != last)
+ {
+ d = lcm(d, *first);
+ first++;
+ }
+ return std::make_pair(d, first);
}
template < typename IntegerType >
-inline
-IntegerType
-lcm
-(
- IntegerType const & a,
- IntegerType const & b
-)
+class gcd_evaluator
+#ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL
+ : public std::binary_function<IntegerType, IntegerType, IntegerType>
+#endif
{
- lcm_evaluator<IntegerType> solver;
-
- return solver( a, b );
-}
+public:
+#ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL
+ typedef IntegerType first_argument_type;
+ typedef IntegerType second_argument_type;
+ typedef IntegerType result_type;
+#endif
+ IntegerType operator()(IntegerType const &a, IntegerType const &b)const
+ {
+ return boost::integer::gcd(a, b);
+ }
+};
+template < typename IntegerType >
+class lcm_evaluator
+#ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL
+ : public std::binary_function<IntegerType, IntegerType, IntegerType>
+#endif
+{
+public:
+#ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL
+ typedef IntegerType first_argument_type;
+ typedef IntegerType second_argument_type;
+ typedef IntegerType result_type;
+#endif
+ IntegerType operator()(IntegerType const &a, IntegerType const &b)const
+ {
+ return boost::integer::lcm(a, b);
+ }
+};
} // namespace integer
} // namespace boost
diff --git a/boost/integer/integer_mask.hpp b/boost/integer/integer_mask.hpp
index 2acf7f7dff..eee4679b84 100644
--- a/boost/integer/integer_mask.hpp
+++ b/boost/integer/integer_mask.hpp
@@ -57,19 +57,27 @@ struct high_bit_mask_t
// Makes masks for the lowest N bits
// (Specializations are needed when N fills up a type.)
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:4310) // cast truncates constant value
+#endif
+
template < std::size_t Bits >
struct low_bits_mask_t
{
typedef typename uint_t<Bits>::least least;
typedef typename uint_t<Bits>::fast fast;
- BOOST_STATIC_CONSTANT( least, sig_bits = (~( ~(least( 0u )) << Bits )) );
+ BOOST_STATIC_CONSTANT( least, sig_bits = least(~(least(~(least( 0u ))) << Bits )) );
BOOST_STATIC_CONSTANT( fast, sig_bits_fast = fast(sig_bits) );
BOOST_STATIC_CONSTANT( std::size_t, bit_count = Bits );
}; // boost::low_bits_mask_t
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
#define BOOST_LOW_BITS_MASK_SPECIALIZE( Type ) \
template < > struct low_bits_mask_t< std::numeric_limits<Type>::digits > { \
diff --git a/boost/integer_fwd.hpp b/boost/integer_fwd.hpp
index 10577ae294..18519dd696 100644
--- a/boost/integer_fwd.hpp
+++ b/boost/integer_fwd.hpp
@@ -159,6 +159,8 @@ template <static_min_max_unsigned_type Value1, static_min_max_unsigned_type Valu
struct static_unsigned_max;
+namespace integer
+{
// From <boost/integer/common_factor_ct.hpp>
#ifdef BOOST_NO_INTEGRAL_INT64_T
@@ -180,6 +182,7 @@ template < typename IntegerType >
template < typename IntegerType >
class lcm_evaluator;
+} // namespace integer
} // namespace boost
diff --git a/boost/interprocess/indexes/iunordered_set_index.hpp b/boost/interprocess/indexes/iunordered_set_index.hpp
index 6cd1452f68..702ef9189f 100644
--- a/boost/interprocess/indexes/iunordered_set_index.hpp
+++ b/boost/interprocess/indexes/iunordered_set_index.hpp
@@ -89,8 +89,10 @@ struct iunordered_set_index_aux
};
struct hash_function
- : std::unary_function<value_type, std::size_t>
{
+ typedef value_type argument_type;
+ typedef std::size_t result_type;
+
std::size_t operator()(const value_type &val) const
{
const char_type *beg = ipcdetail::to_raw_pointer(val.name()),
diff --git a/boost/interprocess/indexes/unordered_map_index.hpp b/boost/interprocess/indexes/unordered_map_index.hpp
index 6a5ad5ddb1..ac009f0ad8 100644
--- a/boost/interprocess/indexes/unordered_map_index.hpp
+++ b/boost/interprocess/indexes/unordered_map_index.hpp
@@ -22,7 +22,6 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
-#include <functional>
#include <boost/intrusive/detail/minimal_pair_header.hpp>
#include <boost/unordered_map.hpp>
#include <boost/interprocess/detail/utilities.hpp>
@@ -54,8 +53,10 @@ struct unordered_map_index_aux
typename MapConfig::
segment_manager_base> allocator_type;
struct hasher
- : std::unary_function<key_type, std::size_t>
{
+ typedef key_type argument_type;
+ typedef std::size_t result_type;
+
std::size_t operator()(const key_type &val) const
{
typedef typename key_type::char_type char_type;
diff --git a/boost/intrusive/bstree.hpp b/boost/intrusive/bstree.hpp
index 1eeab55113..ac67e864a0 100644
--- a/boost/intrusive/bstree.hpp
+++ b/boost/intrusive/bstree.hpp
@@ -255,7 +255,8 @@ struct get_key_of_value<void, T>
template<class ValuePtr, class VoidOrKeyOfValue, class VoidOrKeyComp>
struct bst_key_types
{
- typedef typename pointer_element<ValuePtr>::type value_type;
+ typedef typename
+ boost::movelib::pointer_element<ValuePtr>::type value_type;
typedef typename get_key_of_value
< VoidOrKeyOfValue, value_type>::type key_of_value;
typedef typename key_of_value::type key_type;
diff --git a/boost/intrusive/detail/default_header_holder.hpp b/boost/intrusive/detail/default_header_holder.hpp
index 288f8a0e41..ba561b5f5b 100644
--- a/boost/intrusive/detail/default_header_holder.hpp
+++ b/boost/intrusive/detail/default_header_holder.hpp
@@ -23,7 +23,7 @@
#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/pointer_traits.hpp>
-#include <boost/intrusive/detail/to_raw_pointer.hpp>
+#include <boost/move/detail/to_raw_pointer.hpp>
namespace boost {
namespace intrusive {
@@ -48,7 +48,7 @@ struct default_header_holder : public NodeTraits::node
// (unsafe) downcast used to implement container-from-iterator
BOOST_INTRUSIVE_FORCEINLINE static default_header_holder* get_holder(const node_ptr &p)
- { return static_cast< default_header_holder* >(boost::intrusive::detail::to_raw_pointer(p)); }
+ { return static_cast< default_header_holder* >(boost::movelib::to_raw_pointer(p)); }
};
// type function producing the header node holder
diff --git a/boost/intrusive/detail/ebo_functor_holder.hpp b/boost/intrusive/detail/ebo_functor_holder.hpp
index 31b2f81398..27415c1170 100644
--- a/boost/intrusive/detail/ebo_functor_holder.hpp
+++ b/boost/intrusive/detail/ebo_functor_holder.hpp
@@ -35,7 +35,7 @@ namespace detail {
#define BOOST_INTRUSIVE_TT_DECL
#endif
-#if defined(_MSC_EXTENSIONS) && !defined(__BORLAND__) && !defined(_WIN64) && !defined(_M_ARM) && !defined(UNDER_CE)
+#if defined(_MSC_EXTENSIONS) && !defined(__BORLAND__) && !defined(_WIN64) && !defined(_M_ARM) && !defined(_M_ARM64) && !defined(UNDER_CE)
#define BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS
#endif
diff --git a/boost/intrusive/detail/hashtable_node.hpp b/boost/intrusive/detail/hashtable_node.hpp
index 8f8718e9a7..d3b11d1b22 100644
--- a/boost/intrusive/detail/hashtable_node.hpp
+++ b/boost/intrusive/detail/hashtable_node.hpp
@@ -246,7 +246,7 @@ class hashtable_iterator
void increment()
{
const bucket_traits &rbuck_traits = this->priv_bucket_traits();
- bucket_type* const buckets = boost::intrusive::detail::to_raw_pointer(rbuck_traits.bucket_begin());
+ bucket_type* const buckets = boost::movelib::to_raw_pointer(rbuck_traits.bucket_begin());
const size_type buckets_len = rbuck_traits.bucket_count();
++slist_it_;
diff --git a/boost/intrusive/detail/hook_traits.hpp b/boost/intrusive/detail/hook_traits.hpp
index 2a16061a54..7a6f206ca2 100644
--- a/boost/intrusive/detail/hook_traits.hpp
+++ b/boost/intrusive/detail/hook_traits.hpp
@@ -26,7 +26,7 @@
#include <boost/intrusive/detail/parent_from_member.hpp>
#include <boost/intrusive/link_mode.hpp>
#include <boost/intrusive/detail/mpl.hpp>
-#include <boost/intrusive/detail/to_raw_pointer.hpp>
+#include <boost/move/detail/to_raw_pointer.hpp>
#include <boost/intrusive/detail/node_holder.hpp>
namespace boost {
@@ -128,14 +128,14 @@ struct mhtraits
{
return pointer_traits<pointer>::pointer_to
(*detail::parent_from_member<T, Hook>
- (static_cast<Hook*>(boost::intrusive::detail::to_raw_pointer(n)), P));
+ (static_cast<Hook*>(boost::movelib::to_raw_pointer(n)), P));
}
BOOST_INTRUSIVE_FORCEINLINE static const_pointer to_value_ptr(const const_node_ptr & n)
{
return pointer_traits<const_pointer>::pointer_to
(*detail::parent_from_member<T, Hook>
- (static_cast<const Hook*>(boost::intrusive::detail::to_raw_pointer(n)), P));
+ (static_cast<const Hook*>(boost::movelib::to_raw_pointer(n)), P));
}
};
@@ -161,10 +161,10 @@ struct fhtraits
static const link_mode_type link_mode = hook_type::hooktags::link_mode;
static node_ptr to_node_ptr(reference value)
- { return static_cast<node*>(boost::intrusive::detail::to_raw_pointer(Functor::to_hook_ptr(value))); }
+ { return static_cast<node*>(boost::movelib::to_raw_pointer(Functor::to_hook_ptr(value))); }
static const_node_ptr to_node_ptr(const_reference value)
- { return static_cast<const node*>(boost::intrusive::detail::to_raw_pointer(Functor::to_hook_ptr(value))); }
+ { return static_cast<const node*>(boost::movelib::to_raw_pointer(Functor::to_hook_ptr(value))); }
static pointer to_value_ptr(const node_ptr & n)
{ return Functor::to_value_ptr(to_hook_ptr(n)); }
diff --git a/boost/intrusive/detail/iterator.hpp b/boost/intrusive/detail/iterator.hpp
index 2ae6abb7d0..c25be430a2 100644
--- a/boost/intrusive/detail/iterator.hpp
+++ b/boost/intrusive/detail/iterator.hpp
@@ -27,6 +27,24 @@
#include <boost/move/detail/iterator_traits.hpp>
#include <boost/move/detail/meta_utils_core.hpp>
+namespace boost{
+namespace iterators{
+
+struct incrementable_traversal_tag;
+struct single_pass_traversal_tag;
+struct forward_traversal_tag;
+struct bidirectional_traversal_tag;
+struct random_access_traversal_tag;
+
+namespace detail{
+
+template <class Category, class Traversal>
+struct iterator_category_with_traversal;
+
+} //namespace boost{
+} //namespace iterators{
+} //namespace detail{
+
namespace boost {
namespace intrusive {
@@ -46,6 +64,28 @@ struct iterator
};
////////////////////////////////////////
+// iterator_[dis|en]able_if_boost_iterator
+////////////////////////////////////////
+template<class I>
+struct is_boost_iterator
+{
+ static const bool value = false;
+};
+
+template<class Category, class Traversal>
+struct is_boost_iterator< boost::iterators::detail::iterator_category_with_traversal<Category, Traversal> >
+{
+ static const bool value = true;
+};
+
+template<class I, class R = void>
+struct iterator_enable_if_boost_iterator
+ : ::boost::move_detail::enable_if_c
+ < is_boost_iterator<typename boost::intrusive::iterator_traits<I>::iterator_category >::value
+ , R>
+{};
+
+////////////////////////////////////////
// iterator_[dis|en]able_if_tag
////////////////////////////////////////
template<class I, class Tag, class R = void>
@@ -69,6 +109,23 @@ struct iterator_disable_if_tag
{};
////////////////////////////////////////
+// iterator_[dis|en]able_if_tag
+////////////////////////////////////////
+template<class I, class Tag, class Tag2, class R = void>
+struct iterator_enable_if_convertible_tag
+ : ::boost::move_detail::enable_if_c
+ < ::boost::move_detail::is_same_or_convertible
+ < typename boost::intrusive::iterator_traits<I>::iterator_category
+ , Tag
+ >::value &&
+ !::boost::move_detail::is_same_or_convertible
+ < typename boost::intrusive::iterator_traits<I>::iterator_category
+ , Tag2
+ >::value
+ , R>
+{};
+
+////////////////////////////////////////
// iterator_[dis|en]able_if_tag_difference_type
////////////////////////////////////////
template<class I, class Tag>
@@ -84,8 +141,9 @@ struct iterator_disable_if_tag_difference_type
////////////////////
// advance
////////////////////
+
template<class InputIt, class Distance>
-typename iterator_enable_if_tag<InputIt, std::input_iterator_tag>::type
+BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_tag<InputIt, std::input_iterator_tag>::type
iterator_advance(InputIt& it, Distance n)
{
while(n--)
@@ -101,7 +159,7 @@ typename iterator_enable_if_tag<InputIt, std::forward_iterator_tag>::type
}
template<class InputIt, class Distance>
-typename iterator_enable_if_tag<InputIt, std::bidirectional_iterator_tag>::type
+BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_tag<InputIt, std::bidirectional_iterator_tag>::type
iterator_advance(InputIt& it, Distance n)
{
for (; 0 < n; --n)
@@ -117,6 +175,54 @@ BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_tag<InputIt, std::random
it += n;
}
+template<class InputIt, class Distance>
+BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_convertible_tag
+ <InputIt, const boost::iterators::incrementable_traversal_tag&, const boost::iterators::single_pass_traversal_tag&>::type
+ iterator_advance(InputIt& it, Distance n)
+{
+ while(n--)
+ ++it;
+}
+
+template<class InputIt, class Distance>
+BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_convertible_tag
+ <InputIt, const boost::iterators::single_pass_traversal_tag &, const boost::iterators::forward_traversal_tag&>::type
+ iterator_advance(InputIt& it, Distance n)
+{
+ while(n--)
+ ++it;
+}
+
+template<class InputIt, class Distance>
+BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_convertible_tag
+ <InputIt, const boost::iterators::forward_traversal_tag&, const boost::iterators::bidirectional_traversal_tag&>::type
+ iterator_advance(InputIt& it, Distance n)
+{
+ while(n--)
+ ++it;
+}
+
+template<class InputIt, class Distance>
+BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_convertible_tag
+ <InputIt, const boost::iterators::bidirectional_traversal_tag&, const boost::iterators::random_access_traversal_tag&>::type
+ iterator_advance(InputIt& it, Distance n)
+{
+ for (; 0 < n; --n)
+ ++it;
+ for (; n < 0; ++n)
+ --it;
+}
+
+class fake{};
+
+template<class InputIt, class Distance>
+BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_convertible_tag
+ <InputIt, const boost::iterators::random_access_traversal_tag&, const fake&>::type
+ iterator_advance(InputIt& it, Distance n)
+{
+ it += n;
+}
+
////////////////////
// distance
////////////////////
diff --git a/boost/intrusive/detail/node_to_value.hpp b/boost/intrusive/detail/node_to_value.hpp
index 5af3347345..218e78e4e0 100644
--- a/boost/intrusive/detail/node_to_value.hpp
+++ b/boost/intrusive/detail/node_to_value.hpp
@@ -59,7 +59,7 @@ struct constptr
{}
const void *get_ptr() const
- { return boost::intrusive::detail::to_raw_pointer(const_void_ptr_); }
+ { return boost::movelib::to_raw_pointer(const_void_ptr_); }
ConstVoidPtr const_void_ptr_;
};
diff --git a/boost/intrusive/detail/to_raw_pointer.hpp b/boost/intrusive/detail/to_raw_pointer.hpp
deleted file mode 100644
index 8ea884959d..0000000000
--- a/boost/intrusive/detail/to_raw_pointer.hpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/////////////////////////////////////////////////////////////////////////////
-//
-// (C) Copyright Ion Gaztanaga 2014-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)
-//
-// See http://www.boost.org/libs/intrusive for documentation.
-//
-/////////////////////////////////////////////////////////////////////////////
-
-#ifndef BOOST_INTRUSIVE_DETAIL_TO_RAW_POINTER_HPP
-#define BOOST_INTRUSIVE_DETAIL_TO_RAW_POINTER_HPP
-
-#ifndef BOOST_CONFIG_HPP
-# include <boost/config.hpp>
-#endif
-
-#if defined(BOOST_HAS_PRAGMA_ONCE)
-# pragma once
-#endif
-
-#include <boost/intrusive/detail/config_begin.hpp>
-#include <boost/intrusive/detail/workaround.hpp>
-#include <boost/intrusive/detail/pointer_element.hpp>
-
-namespace boost {
-namespace intrusive {
-namespace detail {
-
-template <class T>
-BOOST_INTRUSIVE_FORCEINLINE T* to_raw_pointer(T* p)
-{ return p; }
-
-template <class Pointer>
-BOOST_INTRUSIVE_FORCEINLINE typename boost::intrusive::pointer_element<Pointer>::type*
-to_raw_pointer(const Pointer &p)
-{ return boost::intrusive::detail::to_raw_pointer(p.operator->()); }
-
-} //namespace detail
-} //namespace intrusive
-} //namespace boost
-
-#include <boost/intrusive/detail/config_end.hpp>
-
-#endif //BOOST_INTRUSIVE_DETAIL_UTILITIES_HPP
diff --git a/boost/intrusive/detail/tree_value_compare.hpp b/boost/intrusive/detail/tree_value_compare.hpp
index c8f596fc96..f6dd01dc25 100644
--- a/boost/intrusive/detail/tree_value_compare.hpp
+++ b/boost/intrusive/detail/tree_value_compare.hpp
@@ -37,7 +37,8 @@ struct disable_if_smartref_to
|| detail::is_same
<From, typename pointer_traits
< typename pointer_rebind
- <ValuePtr, const typename pointer_element<ValuePtr>::type>::type>
+ < ValuePtr
+ , const typename boost::movelib::pointer_element<ValuePtr>::type>::type>
::reference>::value
>
{};
@@ -45,11 +46,13 @@ struct disable_if_smartref_to
//This function object takes a KeyCompare function object
//and compares values that contains keys using KeyOfValue
template< class ValuePtr, class KeyCompare, class KeyOfValue
- , bool = boost::intrusive::detail::is_same<typename pointer_element<ValuePtr>::type, typename KeyOfValue::type>::value >
+ , bool = boost::intrusive::detail::is_same
+ <typename boost::movelib::pointer_element<ValuePtr>::type, typename KeyOfValue::type>::value >
struct tree_value_compare
: public boost::intrusive::detail::ebo_functor_holder<KeyCompare>
{
- typedef typename pointer_element<ValuePtr>::type value_type;
+ typedef typename
+ boost::movelib::pointer_element<ValuePtr>::type value_type;
typedef KeyCompare key_compare;
typedef KeyOfValue key_of_value;
typedef typename KeyOfValue::type key_type;
@@ -114,7 +117,8 @@ template<class ValuePtr, class KeyCompare, class KeyOfValue>
struct tree_value_compare<ValuePtr, KeyCompare, KeyOfValue, true>
: public boost::intrusive::detail::ebo_functor_holder<KeyCompare>
{
- typedef typename pointer_element<ValuePtr>::type value_type;
+ typedef typename
+ boost::movelib::pointer_element<ValuePtr>::type value_type;
typedef KeyCompare key_compare;
typedef KeyOfValue key_of_value;
typedef typename KeyOfValue::type key_type;
diff --git a/boost/intrusive/hashtable.hpp b/boost/intrusive/hashtable.hpp
index 313da829d3..bae9d52485 100644
--- a/boost/intrusive/hashtable.hpp
+++ b/boost/intrusive/hashtable.hpp
@@ -117,6 +117,24 @@ struct prime_list_holder
{
static const std::size_t prime_list[];
static const std::size_t prime_list_size;
+
+ static std::size_t suggested_upper_bucket_count(std::size_t n)
+ {
+ const std::size_t *primes = &prime_list_holder<0>::prime_list[0];
+ const std::size_t *primes_end = primes + prime_list_holder<0>::prime_list_size;
+ std::size_t const* bound = std::lower_bound(primes, primes_end, n);
+ bound -= (bound == primes_end);
+ return *bound;
+ }
+
+ static std::size_t suggested_lower_bucket_count(std::size_t n)
+ {
+ const std::size_t *primes = &prime_list_holder<0>::prime_list[0];
+ const std::size_t *primes_end = primes + prime_list_holder<0>::prime_list_size;
+ std::size_t const* bound = std::upper_bound(primes, primes_end, n);
+ bound -= (bound != primes);
+ return *bound;
+ }
};
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
@@ -588,7 +606,6 @@ struct bucket_plus_vtraits
typedef typename value_traits::node_traits node_traits;
typedef unordered_group_adapter<node_traits> group_traits;
typedef typename slist_impl::iterator siterator;
- typedef typename slist_impl::size_type size_type;
typedef detail::bucket_impl<slist_impl> bucket_type;
typedef detail::group_functions<node_traits> group_functions_t;
typedef typename slist_impl::node_algorithms node_algorithms;
@@ -655,7 +672,7 @@ struct bucket_plus_vtraits
BOOST_INTRUSIVE_FORCEINLINE bucket_ptr priv_bucket_pointer() const
{ return this->priv_bucket_traits().bucket_begin(); }
- typename slist_impl::size_type priv_bucket_count() const
+ std::size_t priv_bucket_count() const
{ return this->priv_bucket_traits().bucket_count(); }
BOOST_INTRUSIVE_FORCEINLINE bucket_ptr priv_invalid_bucket() const
@@ -668,9 +685,9 @@ struct bucket_plus_vtraits
{ return this->priv_bucket_traits().bucket_begin()->before_begin(); }
template<class NodeDisposer>
- static size_type priv_erase_from_single_bucket(bucket_type &b, siterator sbefore_first, siterator slast, NodeDisposer node_disposer, detail::true_) //optimize multikey
+ static std::size_t priv_erase_from_single_bucket(bucket_type &b, siterator sbefore_first, siterator slast, NodeDisposer node_disposer, detail::true_) //optimize multikey
{
- size_type n = 0;
+ std::size_t n = 0;
siterator const sfirst(++siterator(sbefore_first));
if(sfirst != slast){
node_ptr const nf = detail::dcast_bucket_ptr<node>(sfirst.pointed_node());
@@ -708,9 +725,9 @@ struct bucket_plus_vtraits
}
template<class NodeDisposer>
- static size_type priv_erase_from_single_bucket(bucket_type &b, siterator sbefore_first, siterator slast, NodeDisposer node_disposer, detail::false_) //optimize multikey
+ static std::size_t priv_erase_from_single_bucket(bucket_type &b, siterator sbefore_first, siterator slast, NodeDisposer node_disposer, detail::false_) //optimize multikey
{
- size_type n = 0;
+ std::size_t n = 0;
siterator it(++siterator(sbefore_first));
while(it != slast){
node_disposer((it++).pointed_node());
@@ -757,17 +774,17 @@ struct bucket_plus_vtraits
{ b.erase_after_and_dispose(b.previous(i), node_disposer); }
template<class NodeDisposer, bool OptimizeMultikey>
- size_type priv_erase_node_range( siterator const &before_first_it, size_type const first_bucket
- , siterator const &last_it, size_type const last_bucket
+ std::size_t priv_erase_node_range( siterator const &before_first_it, std::size_t const first_bucket
+ , siterator const &last_it, std::size_t const last_bucket
, NodeDisposer node_disposer, detail::bool_<OptimizeMultikey> optimize_multikey_tag)
{
- size_type num_erased(0);
+ std::size_t num_erased(0);
siterator last_step_before_it;
if(first_bucket != last_bucket){
bucket_type *b = (&this->priv_bucket_pointer()[0]);
num_erased += this->priv_erase_from_single_bucket
(b[first_bucket], before_first_it, b[first_bucket].end(), node_disposer, optimize_multikey_tag);
- for(size_type i = 0, n = (last_bucket - first_bucket - 1); i != n; ++i){
+ for(std::size_t i = 0, n = (last_bucket - first_bucket - 1); i != n; ++i){
num_erased += this->priv_erase_whole_bucket(b[first_bucket+i+1], node_disposer);
}
last_step_before_it = b[last_bucket].before_begin();
@@ -797,9 +814,9 @@ struct bucket_plus_vtraits
}
template<class NodeDisposer>
- size_type priv_erase_whole_bucket(bucket_type &b, NodeDisposer node_disposer)
+ std::size_t priv_erase_whole_bucket(bucket_type &b, NodeDisposer node_disposer)
{
- size_type num_erased = 0;
+ std::size_t num_erased = 0;
siterator b_begin(b.before_begin());
siterator nxt(b_begin);
++nxt;
@@ -841,7 +858,7 @@ struct bucket_plus_vtraits
const bucket_type &b = static_cast<const bucket_type&>
(bucket_type::slist_type::container_from_end_iterator(bucket_type::s_iterator_to(*bb)));
//Now just calculate the index b has in the bucket array
- return static_cast<size_type>(&b - &*f);
+ return static_cast<std::size_t>(&b - &*f);
}
std::size_t priv_get_bucket_num_no_hash_store(siterator it, detail::false_) //NO optimize multikey
@@ -881,10 +898,10 @@ struct bucket_plus_vtraits
BOOST_INTRUSIVE_FORCEINLINE const_reference priv_value_from_slist_node(slist_node_ptr n) const
{ return *this->priv_value_traits().to_value_ptr(detail::dcast_bucket_ptr<node>(n)); }
- void priv_clear_buckets(const bucket_ptr buckets_ptr, const size_type bucket_cnt)
+ void priv_clear_buckets(const bucket_ptr buckets_ptr, const std::size_t bucket_cnt)
{
bucket_ptr buckets_it = buckets_ptr;
- for(size_type bucket_i = 0; bucket_i != bucket_cnt; ++buckets_it, ++bucket_i){
+ for(std::size_t bucket_i = 0; bucket_i != bucket_cnt; ++buckets_it, ++bucket_i){
if(safemode_or_autounlink){
buckets_it->clear_and_dispose(detail::init_disposer<node_algorithms>());
}
@@ -909,24 +926,6 @@ struct bucket_plus_vtraits
BOOST_INTRUSIVE_FORCEINLINE const_iterator cend() const
{ return const_iterator(this->priv_invalid_local_it(), 0); }
- static size_type suggested_upper_bucket_count(size_type n)
- {
- const std::size_t *primes = &prime_list_holder<0>::prime_list[0];
- const std::size_t *primes_end = primes + prime_list_holder<0>::prime_list_size;
- std::size_t const* bound = std::lower_bound(primes, primes_end, n);
- bound -= (bound == primes_end);
- return size_type(*bound);
- }
-
- static size_type suggested_lower_bucket_count(size_type n)
- {
- const std::size_t *primes = &prime_list_holder<0>::prime_list[0];
- const std::size_t *primes_end = primes + prime_list_holder<0>::prime_list_size;
- size_type const* bound = std::upper_bound(primes, primes_end, n);
- bound -= (bound != primes);
- return size_type(*bound);
- }
-
//Public functions:
struct data_type : public ValueTraits
{
@@ -1072,7 +1071,6 @@ struct bucket_hash_equal_t
typedef typename bucket_hash_type::hasher hasher;
typedef BucketTraits bucket_traits;
typedef typename bucket_plus_vtraits_t::slist_impl slist_impl;
- typedef typename slist_impl::size_type size_type;
typedef typename slist_impl::iterator siterator;
typedef detail::bucket_impl<slist_impl> bucket_type;
typedef typename detail::unordered_bucket_ptr_impl<value_traits>::type bucket_ptr;
@@ -1089,7 +1087,7 @@ struct bucket_hash_equal_t
BOOST_INTRUSIVE_FORCEINLINE void priv_set_cache(const bucket_ptr &)
{}
- BOOST_INTRUSIVE_FORCEINLINE size_type priv_get_cache_bucket_num()
+ BOOST_INTRUSIVE_FORCEINLINE std::size_t priv_get_cache_bucket_num()
{ return 0u; }
BOOST_INTRUSIVE_FORCEINLINE void priv_initialize_cache()
@@ -1100,8 +1098,8 @@ struct bucket_hash_equal_t
siterator priv_begin() const
{
- size_type n = 0;
- size_type bucket_cnt = this->bucket_hash_type::priv_bucket_count();
+ std::size_t n = 0;
+ std::size_t bucket_cnt = this->bucket_hash_type::priv_bucket_count();
for (n = 0; n < bucket_cnt; ++n){
bucket_type &b = this->bucket_hash_type::priv_bucket_pointer()[n];
if(!b.empty()){
@@ -1111,10 +1109,10 @@ struct bucket_hash_equal_t
return this->bucket_hash_type::priv_invalid_local_it();
}
- BOOST_INTRUSIVE_FORCEINLINE void priv_insertion_update_cache(size_type)
+ BOOST_INTRUSIVE_FORCEINLINE void priv_insertion_update_cache(std::size_t)
{}
- BOOST_INTRUSIVE_FORCEINLINE void priv_erasure_update_cache_range(size_type, size_type)
+ BOOST_INTRUSIVE_FORCEINLINE void priv_erasure_update_cache_range(std::size_t, std::size_t)
{}
BOOST_INTRUSIVE_FORCEINLINE void priv_erasure_update_cache()
@@ -1145,7 +1143,6 @@ struct bucket_hash_equal_t<ValueTraits, VoidOrKeyOfValue, VoidOrKeyHash, VoidOrK
typedef bucket_hash_t<ValueTraits, VoidOrKeyOfValue, VoidOrKeyHash, BucketTraits> bucket_hash_type;
typedef typename bucket_hash_type::hasher hasher;
typedef BucketTraits bucket_traits;
- typedef typename bucket_plus_vtraits_t::slist_impl::size_type size_type;
typedef typename bucket_plus_vtraits_t::slist_impl::iterator siterator;
template<class BucketTraitsType>
@@ -1187,7 +1184,7 @@ struct bucket_hash_equal_t<ValueTraits, VoidOrKeyOfValue, VoidOrKeyHash, VoidOrK
}
}
- void priv_insertion_update_cache(size_type insertion_bucket)
+ void priv_insertion_update_cache(std::size_t insertion_bucket)
{
bucket_ptr p = this->bucket_hash_type::priv_bucket_pointer() + insertion_bucket;
if(p < this->cached_begin_){
@@ -1201,7 +1198,7 @@ struct bucket_hash_equal_t<ValueTraits, VoidOrKeyOfValue, VoidOrKeyHash, VoidOrK
BOOST_INTRUSIVE_FORCEINLINE key_equal &priv_equal()
{ return this->equal_holder_t::get(); }
- void priv_erasure_update_cache_range(size_type first_bucket_num, size_type last_bucket_num)
+ void priv_erasure_update_cache_range(std::size_t first_bucket_num, std::size_t last_bucket_num)
{
//If the last bucket is the end, the cache must be updated
//to the last position if all
@@ -1215,8 +1212,8 @@ struct bucket_hash_equal_t<ValueTraits, VoidOrKeyOfValue, VoidOrKeyHash, VoidOrK
void priv_erasure_update_cache()
{
if(this->cached_begin_ != this->bucket_hash_type::priv_invalid_bucket()){
- size_type current_n = this->priv_get_cache() - this->bucket_hash_type::priv_bucket_pointer();
- for( const size_type num_buckets = this->bucket_hash_type::priv_bucket_count()
+ std::size_t current_n = this->priv_get_cache() - this->bucket_hash_type::priv_bucket_pointer();
+ for( const std::size_t num_buckets = this->bucket_hash_type::priv_bucket_count()
; current_n < num_buckets
; ++current_n, ++this->priv_get_cache()){
if(!this->priv_get_cache()->empty()){
@@ -1307,7 +1304,7 @@ struct hashdata_internal
typedef typename internal_type::key_equal key_equal;
typedef typename internal_type::hasher hasher;
typedef bucket_plus_vtraits<ValueTraits,BucketTraits> bucket_plus_vtraits_t;
- typedef typename bucket_plus_vtraits_t::size_type size_type;
+ typedef SizeType size_type;
typedef typename internal_type::size_traits split_traits;
typedef typename bucket_plus_vtraits_t::bucket_ptr bucket_ptr;
typedef typename bucket_plus_vtraits_t::const_value_traits_ptr const_value_traits_ptr;
@@ -1459,7 +1456,11 @@ struct hashdata_internal
}
BOOST_INTRUSIVE_FORCEINLINE size_type bucket_count() const
- { return this->priv_bucket_count(); }
+ {
+ const std::size_t bc = this->priv_bucket_count();
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(sizeof(size_type) >= sizeof(std::size_t) || bc <= size_type(-1));
+ return static_cast<size_type>(bc);
+ }
BOOST_INTRUSIVE_FORCEINLINE size_type bucket_size(size_type n) const
{ return this->priv_bucket_pointer()[n].size(); }
@@ -1473,6 +1474,20 @@ struct hashdata_internal
BOOST_INTRUSIVE_FORCEINLINE const_local_iterator begin(size_type n) const
{ return this->cbegin(n); }
+ static BOOST_INTRUSIVE_FORCEINLINE size_type suggested_upper_bucket_count(size_type n)
+ {
+ std::size_t c = prime_list_holder<0>::suggested_upper_bucket_count
+ (sizeof(size_type) > sizeof(std::size_t) && n > std::size_t(-1) ? std::size_t(-1) : static_cast<std::size_t>(n));
+ return sizeof(size_type) < sizeof(std::size_t) && c > size_type(-1) ? size_type(-1) : static_cast<size_type>(c);
+ }
+
+ static BOOST_INTRUSIVE_FORCEINLINE size_type suggested_lower_bucket_count(size_type n)
+ {
+ std::size_t c = prime_list_holder<0>::suggested_lower_bucket_count
+ (sizeof(size_type) > sizeof(std::size_t) && n > std::size_t(-1) ? std::size_t(-1) : static_cast<std::size_t>(n));
+ return sizeof(size_type) < sizeof(std::size_t) && c > size_type(-1) ? size_type(-1) : static_cast<size_type>(c);
+ }
+
const_local_iterator cbegin(size_type n) const
{
return const_local_iterator
@@ -1737,7 +1752,7 @@ class hashtable_impl
{
this->priv_initialize_buckets_and_cache();
this->priv_size_traits().set_size(size_type(0));
- size_type bucket_sz = this->priv_bucket_count();
+ size_type bucket_sz = this->bucket_count();
BOOST_INTRUSIVE_INVARIANT_ASSERT(bucket_sz != 0);
//Check power of two bucket array if the option is activated
BOOST_INTRUSIVE_INVARIANT_ASSERT
@@ -1770,7 +1785,7 @@ class hashtable_impl
{
this->priv_initialize_buckets_and_cache();
this->priv_size_traits().set_size(size_type(0));
- size_type bucket_sz = this->priv_bucket_count();
+ size_type bucket_sz = this->bucket_count();
BOOST_INTRUSIVE_INVARIANT_ASSERT(bucket_sz != 0);
//Check power of two bucket array if the option is activated
BOOST_INTRUSIVE_INVARIANT_ASSERT
@@ -1894,8 +1909,8 @@ class hashtable_impl
return this->begin() == this->end();
}
else{
- size_type bucket_cnt = this->priv_bucket_count();
- const bucket_type *b = boost::intrusive::detail::to_raw_pointer(this->priv_bucket_pointer());
+ size_type bucket_cnt = this->bucket_count();
+ const bucket_type *b = boost::movelib::to_raw_pointer(this->priv_bucket_pointer());
for (size_type n = 0; n < bucket_cnt; ++n, ++b){
if(!b->empty()){
return false;
@@ -1917,8 +1932,8 @@ class hashtable_impl
return this->priv_size_traits().get_size();
else{
size_type len = 0;
- size_type bucket_cnt = this->priv_bucket_count();
- const bucket_type *b = boost::intrusive::detail::to_raw_pointer(this->priv_bucket_pointer());
+ size_type bucket_cnt = this->bucket_count();
+ const bucket_type *b = boost::movelib::to_raw_pointer(this->priv_bucket_pointer());
for (size_type n = 0; n < bucket_cnt; ++n, ++b){
len += b->size();
}
@@ -2898,7 +2913,7 @@ class hashtable_impl
//This function is only available for containers with incremental hashing
BOOST_STATIC_ASSERT(( incremental && power_2_buckets ));
const size_type split_idx = this->priv_split_traits().get_size();
- const size_type bucket_cnt = this->priv_bucket_count();
+ const size_type bucket_cnt = this->bucket_count();
const bucket_ptr buck_ptr = this->priv_bucket_pointer();
bool ret = false;
@@ -2961,7 +2976,7 @@ class hashtable_impl
//This function is only available for containers with incremental hashing
BOOST_STATIC_ASSERT(( incremental && power_2_buckets ));
size_type const new_bucket_traits_size = new_bucket_traits.bucket_count();
- size_type const cur_bucket_traits = this->priv_bucket_count();
+ size_type const cur_bucket_traits = this->bucket_count();
const size_type split_idx = this->split_count();
//Test new bucket size is consistent with internal bucket size and split count
@@ -3071,7 +3086,7 @@ class hashtable_impl
const bucket_ptr new_buckets = new_bucket_traits.bucket_begin();
size_type new_bucket_count = new_bucket_traits.bucket_count();
const bucket_ptr old_buckets = this->priv_bucket_pointer();
- size_type old_bucket_count = this->priv_bucket_count();
+ size_type old_bucket_count = this->bucket_count();
//Check power of two bucket array if the option is activated
BOOST_INTRUSIVE_INVARIANT_ASSERT
@@ -3400,7 +3415,7 @@ class hashtable_impl
to_return.second == bp[n_bucket].end()){
to_return.second = this->priv_invalid_local_it();
++n_bucket;
- for( const size_type max_bucket = this->priv_bucket_count()
+ for( const size_type max_bucket = this->bucket_count()
; n_bucket != max_bucket
; ++n_bucket){
bucket_type &b = bp[n_bucket];
diff --git a/boost/intrusive/member_value_traits.hpp b/boost/intrusive/member_value_traits.hpp
index 4efe79ebdb..0ab7ffb112 100644
--- a/boost/intrusive/member_value_traits.hpp
+++ b/boost/intrusive/member_value_traits.hpp
@@ -18,7 +18,7 @@
#include <boost/intrusive/link_mode.hpp>
#include <boost/intrusive/detail/parent_from_member.hpp>
-#include <boost/intrusive/detail/to_raw_pointer.hpp>
+#include <boost/move/detail/to_raw_pointer.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
@@ -66,13 +66,13 @@ struct member_value_traits
BOOST_INTRUSIVE_FORCEINLINE static pointer to_value_ptr(const node_ptr &n)
{
return pointer_traits<pointer>::pointer_to(*detail::parent_from_member<value_type, node>
- (boost::intrusive::detail::to_raw_pointer(n), PtrToMember));
+ (boost::movelib::to_raw_pointer(n), PtrToMember));
}
BOOST_INTRUSIVE_FORCEINLINE static const_pointer to_value_ptr(const const_node_ptr &n)
{
return pointer_traits<const_pointer>::pointer_to(*detail::parent_from_member<value_type, node>
- (boost::intrusive::detail::to_raw_pointer(n), PtrToMember));
+ (boost::movelib::to_raw_pointer(n), PtrToMember));
}
};
diff --git a/boost/intrusive/pointer_traits.hpp b/boost/intrusive/pointer_traits.hpp
index 5baf5e807c..4216c7ee9c 100644
--- a/boost/intrusive/pointer_traits.hpp
+++ b/boost/intrusive/pointer_traits.hpp
@@ -20,7 +20,7 @@
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/pointer_rebind.hpp>
-#include <boost/intrusive/detail/pointer_element.hpp>
+#include <boost/move/detail/pointer_element.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <cstddef>
@@ -97,7 +97,7 @@ struct pointer_traits
//
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT
( boost::intrusive::detail::, Ptr, element_type
- , boost::intrusive::detail::first_param<Ptr>) element_type;
+ , boost::movelib::detail::first_param<Ptr>) element_type;
//
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
(boost::intrusive::detail::, Ptr, difference_type, std::ptrdiff_t) difference_type;
diff --git a/boost/intrusive_ptr.hpp b/boost/intrusive_ptr.hpp
index 63036dcd6e..c43adbdc0d 100644
--- a/boost/intrusive_ptr.hpp
+++ b/boost/intrusive_ptr.hpp
@@ -10,7 +10,7 @@
// 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/intrusive_ptr.html for documentation.
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
//
#include <boost/smart_ptr/intrusive_ptr.hpp>
diff --git a/boost/iostreams/detail/adapter/non_blocking_adapter.hpp b/boost/iostreams/detail/adapter/non_blocking_adapter.hpp
index 1457032c71..623cf769d2 100755
--- a/boost/iostreams/detail/adapter/non_blocking_adapter.hpp
+++ b/boost/iostreams/detail/adapter/non_blocking_adapter.hpp
@@ -41,6 +41,9 @@ public:
while (result < n) {
std::streamsize amt =
iostreams::write(device_, s + result, n - result);
+ // write errors, like EOF on read, need to be handled.
+ if (amt == -1)
+ break;
result += amt;
}
return result;
diff --git a/boost/iostreams/detail/config/dyn_link.hpp b/boost/iostreams/detail/config/dyn_link.hpp
index 15490cfe4d..cc8c73bd90 100644
--- a/boost/iostreams/detail/config/dyn_link.hpp
+++ b/boost/iostreams/detail/config/dyn_link.hpp
@@ -27,7 +27,16 @@
# else
# define BOOST_IOSTREAMS_DECL __declspec(dllimport)
# endif
-# endif
+# endif
+//--------------Enable dynamic linking for non-windows---------------------//
+#else // BOOST_HAS_DECLSPEC
+# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_IOSTREAMS_DYN_LINK)
+# ifdef BOOST_IOSTREAMS_SOURCE
+# define BOOST_IOSTREAMS_DECL BOOST_SYMBOL_EXPORT
+# else
+# define BOOST_IOSTREAMS_DECL BOOST_SYMBOL_IMPORT
+# endif
+# endif
#endif
#ifndef BOOST_IOSTREAMS_DECL
diff --git a/boost/iostreams/filter/gzip.hpp b/boost/iostreams/filter/gzip.hpp
index d7939c82d2..e236983e0b 100644
--- a/boost/iostreams/filter/gzip.hpp
+++ b/boost/iostreams/filter/gzip.hpp
@@ -671,7 +671,7 @@ basic_gzip_compressor<Alloc>::basic_gzip_compressor
0 );
header_.reserve(length);
header_ += gzip::magic::id1; // ID1.
- header_ += gzip::magic::id2; // ID2.
+ header_ += static_cast<char>(gzip::magic::id2); // ID2.
header_ += gzip::method::deflate; // CM.
header_ += static_cast<char>(flags); // FLG.
header_ += static_cast<char>(0xFF & p.mtime); // MTIME.
diff --git a/boost/iostreams/filter/lzma.hpp b/boost/iostreams/filter/lzma.hpp
new file mode 100644
index 0000000000..f15f6794a7
--- /dev/null
+++ b/boost/iostreams/filter/lzma.hpp
@@ -0,0 +1,364 @@
+// (C) Copyright Milan Svoboda 2008.
+// Originally developed under the fusecompress project.
+// Distributed under the 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/iostreams for documentation.
+
+// Note: custom allocators are not supported on VC6, since that compiler
+// had trouble finding the function lzma_base::do_init.
+
+#ifndef BOOST_IOSTREAMS_LZMA_HPP_INCLUDED
+#define BOOST_IOSTREAMS_LZMA_HPP_INCLUDED
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <cassert>
+#include <iosfwd> // streamsize.
+#include <memory> // allocator, bad_alloc.
+#include <new>
+#include <boost/config.hpp> // MSVC, STATIC_CONSTANT, DEDUCED_TYPENAME, DINKUM.
+#include <boost/detail/workaround.hpp>
+#include <boost/iostreams/constants.hpp> // buffer size.
+#include <boost/iostreams/detail/config/auto_link.hpp>
+#include <boost/iostreams/detail/config/dyn_link.hpp>
+#include <boost/iostreams/detail/config/wide_streams.hpp>
+#include <boost/iostreams/detail/ios.hpp> // failure, streamsize.
+#include <boost/iostreams/filter/symmetric.hpp>
+#include <boost/iostreams/pipeline.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+// Must come last.
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable:4251 4231 4660) // Dependencies not exported.
+#endif
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost { namespace iostreams {
+
+namespace lzma {
+
+typedef void* (*alloc_func)(void*, size_t, size_t);
+typedef void (*free_func)(void*, void*);
+
+ // Compression levels
+
+BOOST_IOSTREAMS_DECL extern const uint32_t no_compression;
+BOOST_IOSTREAMS_DECL extern const uint32_t best_speed;
+BOOST_IOSTREAMS_DECL extern const uint32_t best_compression;
+BOOST_IOSTREAMS_DECL extern const uint32_t default_compression;
+
+ // Status codes
+
+BOOST_IOSTREAMS_DECL extern const int okay;
+BOOST_IOSTREAMS_DECL extern const int stream_end;
+BOOST_IOSTREAMS_DECL extern const int unsupported_check;
+BOOST_IOSTREAMS_DECL extern const int mem_error;
+BOOST_IOSTREAMS_DECL extern const int options_error;
+BOOST_IOSTREAMS_DECL extern const int data_error;
+BOOST_IOSTREAMS_DECL extern const int buf_error;
+BOOST_IOSTREAMS_DECL extern const int prog_error;
+
+ // Flush codes
+
+BOOST_IOSTREAMS_DECL extern const int finish;
+BOOST_IOSTREAMS_DECL extern const int full_flush;
+BOOST_IOSTREAMS_DECL extern const int sync_flush;
+BOOST_IOSTREAMS_DECL extern const int run;
+
+ // Code for current OS
+
+ // Null pointer constant.
+
+const int null = 0;
+
+ // Default values
+
+} // End namespace lzma.
+
+//
+// Class name: lzma_params.
+// Description: Encapsulates the parameters passed to lzmadec_init
+// to customize compression and decompression.
+//
+struct lzma_params {
+
+ // Non-explicit constructor.
+ lzma_params( uint32_t level = lzma::default_compression )
+ : level(level)
+ { }
+ uint32_t level;
+};
+
+//
+// Class name: lzma_error.
+// Description: Subclass of std::ios::failure thrown to indicate
+// lzma errors other than out-of-memory conditions.
+//
+class BOOST_IOSTREAMS_DECL lzma_error : public BOOST_IOSTREAMS_FAILURE {
+public:
+ explicit lzma_error(int error);
+ int error() const { return error_; }
+ static void check BOOST_PREVENT_MACRO_SUBSTITUTION(int error);
+private:
+ int error_;
+};
+
+namespace detail {
+
+template<typename Alloc>
+struct lzma_allocator_traits {
+#ifndef BOOST_NO_STD_ALLOCATOR
+ typedef typename Alloc::template rebind<char>::other type;
+#else
+ typedef std::allocator<char> type;
+#endif
+};
+
+template< typename Alloc,
+ typename Base = // VC6 workaround (C2516)
+ BOOST_DEDUCED_TYPENAME lzma_allocator_traits<Alloc>::type >
+struct lzma_allocator : private Base {
+private:
+ typedef typename Base::size_type size_type;
+public:
+ BOOST_STATIC_CONSTANT(bool, custom =
+ (!is_same<std::allocator<char>, Base>::value));
+ typedef typename lzma_allocator_traits<Alloc>::type allocator_type;
+ static void* allocate(void* self, size_t items, size_t size);
+ static void deallocate(void* self, void* address);
+};
+
+class BOOST_IOSTREAMS_DECL lzma_base {
+public:
+ typedef char char_type;
+protected:
+ lzma_base();
+ ~lzma_base();
+ void* stream() { return stream_; }
+ template<typename Alloc>
+ void init( const lzma_params& p,
+ bool compress,
+ lzma_allocator<Alloc>& zalloc )
+ {
+ bool custom = lzma_allocator<Alloc>::custom;
+ do_init( p, compress,
+ custom ? lzma_allocator<Alloc>::allocate : 0,
+ custom ? lzma_allocator<Alloc>::deallocate : 0,
+ &zalloc );
+ }
+ void before( const char*& src_begin, const char* src_end,
+ char*& dest_begin, char* dest_end );
+ void after( const char*& src_begin, char*& dest_begin,
+ bool compress );
+ int deflate(int action);
+ int inflate(int action);
+ void reset(bool compress, bool realloc);
+private:
+ void do_init( const lzma_params& p, bool compress,
+ lzma::alloc_func,
+ lzma::free_func,
+ void* derived );
+ void* stream_; // Actual type: lzmadec_stream*.
+ uint32_t level;
+};
+
+//
+// Template name: lzma_compressor_impl
+// Description: Model of C-Style Filter implementing compression by
+// delegating to the lzma function deflate.
+//
+template<typename Alloc = std::allocator<char> >
+class lzma_compressor_impl : public lzma_base, public lzma_allocator<Alloc> {
+public:
+ lzma_compressor_impl(const lzma_params& = lzma::default_compression);
+ ~lzma_compressor_impl();
+ bool filter( const char*& src_begin, const char* src_end,
+ char*& dest_begin, char* dest_end, bool flush );
+ void close();
+};
+
+//
+// Template name: lzma_compressor_impl
+// Description: Model of C-Style Filte implementing decompression by
+// delegating to the lzma function inflate.
+//
+template<typename Alloc = std::allocator<char> >
+class lzma_decompressor_impl : public lzma_base, public lzma_allocator<Alloc> {
+public:
+ lzma_decompressor_impl(const lzma_params&);
+ lzma_decompressor_impl();
+ ~lzma_decompressor_impl();
+ bool filter( const char*& begin_in, const char* end_in,
+ char*& begin_out, char* end_out, bool flush );
+ void close();
+};
+
+} // End namespace detail.
+
+//
+// Template name: lzma_compressor
+// Description: Model of InputFilter and OutputFilter implementing
+// compression using lzma.
+//
+template<typename Alloc = std::allocator<char> >
+struct basic_lzma_compressor
+ : symmetric_filter<detail::lzma_compressor_impl<Alloc>, Alloc>
+{
+private:
+ typedef detail::lzma_compressor_impl<Alloc> impl_type;
+ typedef symmetric_filter<impl_type, Alloc> base_type;
+public:
+ typedef typename base_type::char_type char_type;
+ typedef typename base_type::category category;
+ basic_lzma_compressor( const lzma_params& = lzma::default_compression,
+ std::streamsize buffer_size = default_device_buffer_size );
+};
+BOOST_IOSTREAMS_PIPABLE(basic_lzma_compressor, 1)
+
+typedef basic_lzma_compressor<> lzma_compressor;
+
+//
+// Template name: lzma_decompressor
+// Description: Model of InputFilter and OutputFilter implementing
+// decompression using lzma.
+//
+template<typename Alloc = std::allocator<char> >
+struct basic_lzma_decompressor
+ : symmetric_filter<detail::lzma_decompressor_impl<Alloc>, Alloc>
+{
+private:
+ typedef detail::lzma_decompressor_impl<Alloc> impl_type;
+ typedef symmetric_filter<impl_type, Alloc> base_type;
+public:
+ typedef typename base_type::char_type char_type;
+ typedef typename base_type::category category;
+ basic_lzma_decompressor( std::streamsize buffer_size = default_device_buffer_size );
+ basic_lzma_decompressor( const lzma_params& p,
+ std::streamsize buffer_size = default_device_buffer_size );
+};
+BOOST_IOSTREAMS_PIPABLE(basic_lzma_decompressor, 1)
+
+typedef basic_lzma_decompressor<> lzma_decompressor;
+
+//----------------------------------------------------------------------------//
+
+//------------------Implementation of lzma_allocator--------------------------//
+
+namespace detail {
+
+template<typename Alloc, typename Base>
+void* lzma_allocator<Alloc, Base>::allocate
+ (void* self, size_t items, size_t size)
+{
+ size_type len = items * size;
+ char* ptr =
+ static_cast<allocator_type*>(self)->allocate
+ (len + sizeof(size_type)
+ #if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1)
+ , (char*)0
+ #endif
+ );
+ *reinterpret_cast<size_type*>(ptr) = len;
+ return ptr + sizeof(size_type);
+}
+
+template<typename Alloc, typename Base>
+void lzma_allocator<Alloc, Base>::deallocate(void* self, void* address)
+{
+ char* ptr = reinterpret_cast<char*>(address) - sizeof(size_type);
+ size_type len = *reinterpret_cast<size_type*>(ptr) + sizeof(size_type);
+ static_cast<allocator_type*>(self)->deallocate(ptr, len);
+}
+
+//------------------Implementation of lzma_compressor_impl--------------------//
+
+template<typename Alloc>
+lzma_compressor_impl<Alloc>::lzma_compressor_impl(const lzma_params& p)
+{ init(p, true, static_cast<lzma_allocator<Alloc>&>(*this)); }
+
+template<typename Alloc>
+lzma_compressor_impl<Alloc>::~lzma_compressor_impl()
+{ reset(true, false); }
+
+template<typename Alloc>
+bool lzma_compressor_impl<Alloc>::filter
+ ( const char*& src_begin, const char* src_end,
+ char*& dest_begin, char* dest_end, bool flush )
+{
+ before(src_begin, src_end, dest_begin, dest_end);
+ int result = deflate(flush ? lzma::finish : lzma::run);
+ after(src_begin, dest_begin, true);
+ lzma_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result);
+ return result != lzma::stream_end;
+}
+
+template<typename Alloc>
+void lzma_compressor_impl<Alloc>::close() { reset(true, true); }
+
+//------------------Implementation of lzma_decompressor_impl------------------//
+
+template<typename Alloc>
+lzma_decompressor_impl<Alloc>::lzma_decompressor_impl(const lzma_params& p)
+{ init(p, false, static_cast<lzma_allocator<Alloc>&>(*this)); }
+
+template<typename Alloc>
+lzma_decompressor_impl<Alloc>::~lzma_decompressor_impl()
+{ reset(false, false); }
+
+template<typename Alloc>
+lzma_decompressor_impl<Alloc>::lzma_decompressor_impl()
+{
+ lzma_params p;
+ init(p, false, static_cast<lzma_allocator<Alloc>&>(*this));
+}
+
+template<typename Alloc>
+bool lzma_decompressor_impl<Alloc>::filter
+ ( const char*& src_begin, const char* src_end,
+ char*& dest_begin, char* dest_end, bool flush )
+{
+ before(src_begin, src_end, dest_begin, dest_end);
+ int result = inflate(flush ? lzma::finish : lzma::run);
+ after(src_begin, dest_begin, false);
+ lzma_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result);
+ return result != lzma::stream_end;
+}
+
+template<typename Alloc>
+void lzma_decompressor_impl<Alloc>::close() { reset(false, true); }
+
+} // End namespace detail.
+
+//------------------Implementation of lzma_compressor-----------------------//
+
+template<typename Alloc>
+basic_lzma_compressor<Alloc>::basic_lzma_compressor
+ (const lzma_params& p, std::streamsize buffer_size)
+ : base_type(buffer_size, p) { }
+
+//------------------Implementation of lzma_decompressor-----------------------//
+
+template<typename Alloc>
+basic_lzma_decompressor<Alloc>::basic_lzma_decompressor
+ (std::streamsize buffer_size)
+ : base_type(buffer_size) { }
+
+template<typename Alloc>
+basic_lzma_decompressor<Alloc>::basic_lzma_decompressor
+ (const lzma_params& p, std::streamsize buffer_size)
+ : base_type(buffer_size, p) { }
+
+//----------------------------------------------------------------------------//
+
+} } // End namespaces iostreams, boost.
+
+#include <boost/config/abi_suffix.hpp> // Pops abi_suffix.hpp pragmas.
+#ifdef BOOST_MSVC
+# pragma warning(pop)
+#endif
+
+#endif // #ifndef BOOST_IOSTREAMS_LZMA_HPP_INCLUDED
diff --git a/boost/iterator/advance.hpp b/boost/iterator/advance.hpp
new file mode 100644
index 0000000000..6f81cdb6b1
--- /dev/null
+++ b/boost/iterator/advance.hpp
@@ -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)
+
+#ifndef BOOST_ITERATOR_ADVANCE_HPP
+#define BOOST_ITERATOR_ADVANCE_HPP
+
+#include <boost/config.hpp>
+#include <boost/iterator/iterator_categories.hpp>
+
+namespace boost {
+namespace iterators {
+
+ namespace detail {
+ template <typename InputIterator, typename Distance>
+ inline BOOST_CXX14_CONSTEXPR void
+ advance_impl(
+ InputIterator& it
+ , Distance n
+ , incrementable_traversal_tag
+ )
+ {
+ while (n > 0) {
+ ++it;
+ --n;
+ }
+ }
+
+ template <typename BidirectionalIterator, typename Distance>
+ 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;
+ }
+ }
+ }
+
+ template <typename RandomAccessIterator, typename Distance>
+ inline BOOST_CXX14_CONSTEXPR void
+ advance_impl(
+ RandomAccessIterator& it
+ , Distance n
+ , random_access_traversal_tag
+ )
+ {
+ it += n;
+ }
+ }
+
+ namespace advance_adl_barrier {
+ template <typename InputIterator, typename Distance>
+ inline BOOST_CXX14_CONSTEXPR void
+ advance(InputIterator& it, Distance n)
+ {
+ detail::advance_impl(
+ it, n, typename iterator_traversal<InputIterator>::type()
+ );
+ }
+ }
+
+ using namespace advance_adl_barrier;
+
+} // namespace iterators
+
+using iterators::advance;
+
+} // namespace boost
+
+#endif
diff --git a/boost/iterator/distance.hpp b/boost/iterator/distance.hpp
new file mode 100644
index 0000000000..8cf3f15c44
--- /dev/null
+++ b/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 <boost/config.hpp>
+#include <boost/iterator/iterator_categories.hpp>
+#include <boost/iterator/iterator_traits.hpp>
+
+namespace boost {
+namespace iterators {
+
+ namespace detail {
+ template <typename SinglePassIterator>
+ inline BOOST_CXX14_CONSTEXPR typename iterator_difference<SinglePassIterator>::type
+ distance_impl(
+ SinglePassIterator first
+ , SinglePassIterator last
+ , single_pass_traversal_tag
+ )
+ {
+ typename iterator_difference<SinglePassIterator>::type n = 0;
+ while (first != last) {
+ ++first;
+ ++n;
+ }
+ return n;
+ }
+
+ template <typename RandomAccessIterator>
+ inline BOOST_CXX14_CONSTEXPR typename iterator_difference<RandomAccessIterator>::type
+ distance_impl(
+ RandomAccessIterator first
+ , RandomAccessIterator last
+ , random_access_traversal_tag
+ )
+ {
+ return last - first;
+ }
+ }
+
+ namespace distance_adl_barrier {
+ template <typename SinglePassIterator>
+ inline BOOST_CXX14_CONSTEXPR typename iterator_difference<SinglePassIterator>::type
+ distance(SinglePassIterator first, SinglePassIterator last)
+ {
+ return detail::distance_impl(
+ first, last, typename iterator_traversal<SinglePassIterator>::type()
+ );
+ }
+ }
+
+ using namespace distance_adl_barrier;
+
+} // namespace iterators
+
+using iterators::distance;
+
+} // namespace boost
+
+#endif
diff --git a/boost/iterator/reverse_iterator.hpp b/boost/iterator/reverse_iterator.hpp
index 3bef39e4b6..7ed6b1b5ef 100644
--- a/boost/iterator/reverse_iterator.hpp
+++ b/boost/iterator/reverse_iterator.hpp
@@ -7,7 +7,6 @@
#ifndef BOOST_REVERSE_ITERATOR_23022003THW_HPP
#define BOOST_REVERSE_ITERATOR_23022003THW_HPP
-#include <boost/next_prior.hpp>
#include <boost/iterator.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
@@ -40,14 +39,19 @@ namespace iterators {
{}
private:
- typename super_t::reference dereference() const { return *boost::prior(this->base()); }
+ 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;
+ this->base_reference() -= n;
}
template <class OtherIterator>
diff --git a/boost/iterator/zip_iterator.hpp b/boost/iterator/zip_iterator.hpp
index 83fa63b2a7..3675c0f802 100644
--- a/boost/iterator/zip_iterator.hpp
+++ b/boost/iterator/zip_iterator.hpp
@@ -84,7 +84,7 @@ namespace iterators {
struct result<This(Iterator)>
{
typedef typename
- remove_reference<typename remove_cv<Iterator>::type>::type
+ remove_cv<typename remove_reference<Iterator>::type>::type
iterator;
typedef typename iterator_reference<iterator>::type type;
diff --git a/boost/locale/message.hpp b/boost/locale/message.hpp
index ec8f99f280..a56bb8ada3 100644
--- a/boost/locale/message.hpp
+++ b/boost/locale/message.hpp
@@ -20,6 +20,13 @@
#include <memory>
#include <boost/locale/formatting.hpp>
+// glibc < 2.3.4 declares those as macros if compiled with optimization turned on
+#ifdef gettext
+# undef gettext
+# undef ngettext
+# undef dgettext
+# undef dngettext
+#endif
namespace boost {
namespace locale {
diff --git a/boost/log/core/record_view.hpp b/boost/log/core/record_view.hpp
index 515627aebd..ea18f7a1af 100644
--- a/boost/log/core/record_view.hpp
+++ b/boost/log/core/record_view.hpp
@@ -110,7 +110,7 @@ public:
* \post <tt>!*this == true</tt>
*/
BOOST_CONSTEXPR record_view() BOOST_NOEXCEPT
-#if !defined(BOOST_LOG_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS)
+#if !defined(BOOST_LOG_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS) && !defined(BOOST_LOG_NO_CXX11_DEFAULTED_CONSTEXPR_CONSTRUCTORS)
= default;
#else
{}
diff --git a/boost/log/detail/config.hpp b/boost/log/detail/config.hpp
index 7265d2b6e4..c0bd84744f 100644
--- a/boost/log/detail/config.hpp
+++ b/boost/log/detail/config.hpp
@@ -144,6 +144,11 @@
#define BOOST_LOG_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
#endif
+#if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || (defined(BOOST_CLANG) && (((__clang_major__+0) == 3) && ((__clang_minor__+0) <= 1)))
+// Clang 3.1 cannot handle a defaulted constexpr constructor in some cases (presumably, if the class contains a member with a constexpr constructor)
+#define BOOST_LOG_NO_CXX11_DEFAULTED_CONSTEXPR_CONSTRUCTORS
+#endif
+
#if defined(_MSC_VER)
# define BOOST_LOG_NO_VTABLE __declspec(novtable)
#elif defined(__GNUC__)
diff --git a/boost/make_shared.hpp b/boost/make_shared.hpp
index c04938f9b3..588fbfde1b 100644
--- a/boost/make_shared.hpp
+++ b/boost/make_shared.hpp
@@ -9,8 +9,7 @@
// 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/make_shared.html
-// for documentation.
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
#include <boost/smart_ptr/make_shared.hpp>
diff --git a/boost/math/common_factor_ct.hpp b/boost/math/common_factor_ct.hpp
index bf58b94eb2..3ca0905945 100644
--- a/boost/math/common_factor_ct.hpp
+++ b/boost/math/common_factor_ct.hpp
@@ -1,6 +1,6 @@
// Boost common_factor_ct.hpp header file ----------------------------------//
-// (C) Copyright Daryle Walker and Stephen Cleary 2001-2002.
+// (C) Copyright John Maddock 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)
@@ -10,85 +10,16 @@
#ifndef BOOST_MATH_COMMON_FACTOR_CT_HPP
#define BOOST_MATH_COMMON_FACTOR_CT_HPP
-#include <boost/math_fwd.hpp> // self include
-#include <boost/config.hpp> // for BOOST_STATIC_CONSTANT, etc.
-#include <boost/mpl/integral_c.hpp>
+#include <boost/integer/common_factor_ct.hpp>
namespace boost
{
namespace math
{
-// Implementation details --------------------------------------------------//
-
-namespace detail
-{
- // Build GCD with Euclid's recursive algorithm
- template < static_gcd_type Value1, static_gcd_type Value2 >
- struct static_gcd_helper_t
- {
- private:
- BOOST_STATIC_CONSTANT( static_gcd_type, new_value1 = Value2 );
- BOOST_STATIC_CONSTANT( static_gcd_type, new_value2 = Value1 % Value2 );
-
- #ifndef __BORLANDC__
- #define BOOST_DETAIL_GCD_HELPER_VAL(Value) static_cast<static_gcd_type>(Value)
- #else
- typedef static_gcd_helper_t self_type;
- #define BOOST_DETAIL_GCD_HELPER_VAL(Value) (self_type:: Value )
- #endif
-
- typedef static_gcd_helper_t< BOOST_DETAIL_GCD_HELPER_VAL(new_value1),
- BOOST_DETAIL_GCD_HELPER_VAL(new_value2) > next_step_type;
-
- #undef BOOST_DETAIL_GCD_HELPER_VAL
-
- public:
- BOOST_STATIC_CONSTANT( static_gcd_type, value = next_step_type::value );
- };
-
- // Non-recursive case
- template < static_gcd_type Value1 >
- struct static_gcd_helper_t< Value1, 0UL >
- {
- BOOST_STATIC_CONSTANT( static_gcd_type, value = Value1 );
- };
-
- // Build the LCM from the GCD
- template < static_gcd_type Value1, static_gcd_type Value2 >
- struct static_lcm_helper_t
- {
- typedef static_gcd_helper_t<Value1, Value2> gcd_type;
-
- BOOST_STATIC_CONSTANT( static_gcd_type, value = Value1 / gcd_type::value
- * Value2 );
- };
-
- // Special case for zero-GCD values
- template < >
- struct static_lcm_helper_t< 0UL, 0UL >
- {
- BOOST_STATIC_CONSTANT( static_gcd_type, value = 0UL );
- };
-
-} // namespace detail
-
-
-// Compile-time greatest common divisor evaluator class declaration --------//
-
-template < static_gcd_type Value1, static_gcd_type Value2 >
-struct static_gcd : public mpl::integral_c<static_gcd_type, (detail::static_gcd_helper_t<Value1, Value2>::value) >
-{
-}; // boost::math::static_gcd
-
-
-// Compile-time least common multiple evaluator class declaration ----------//
-
-template < static_gcd_type Value1, static_gcd_type Value2 >
-struct static_lcm : public mpl::integral_c<static_gcd_type, (detail::static_lcm_helper_t<Value1, Value2>::value) >
-{
-}; // boost::math::static_lcm
-
+ using boost::integer::static_gcd;
+ using boost::integer::static_lcm;
+ using boost::integer::static_gcd_type;
} // namespace math
} // namespace boost
diff --git a/boost/math/common_factor_rt.hpp b/boost/math/common_factor_rt.hpp
index acde21d2c8..42d9edfc04 100644
--- a/boost/math/common_factor_rt.hpp
+++ b/boost/math/common_factor_rt.hpp
@@ -1,4 +1,4 @@
-// (C) Copyright Jeremy William Murphy 2016.
+// (C) Copyright John Maddock 2017.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
@@ -7,422 +7,19 @@
#ifndef BOOST_MATH_COMMON_FACTOR_RT_HPP
#define BOOST_MATH_COMMON_FACTOR_RT_HPP
-#include <boost/assert.hpp>
-#include <boost/core/enable_if.hpp>
-#include <boost/mpl/and.hpp>
-#include <boost/type_traits.hpp>
-
-#include <boost/config.hpp> // for BOOST_NESTED_TEMPLATE, etc.
-#include <boost/limits.hpp> // for std::numeric_limits
-#include <climits> // for CHAR_MIN
-#include <boost/detail/workaround.hpp>
-#include <iterator>
-#include <algorithm>
-#include <limits>
-
-#if (defined(BOOST_MSVC) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
-#include <intrin.h>
-#endif
-
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127 4244) // Conditional expression is constant
-#endif
+#include <boost/integer/common_factor_rt.hpp>
namespace boost {
namespace math {
- template <class T, bool a = is_unsigned<T>::value || (std::numeric_limits<T>::is_specialized && !std::numeric_limits<T>::is_signed)>
- struct gcd_traits_abs_defaults
- {
- inline static const T& abs(const T& val) { return val; }
- };
- template <class T>
- struct gcd_traits_abs_defaults<T, false>
- {
- inline static T abs(const T& val)
- {
- using std::abs;
- return abs(val);
- }
- };
-
- template <class T>
- struct gcd_traits_defaults : public gcd_traits_abs_defaults<T>
- {
- BOOST_FORCEINLINE static unsigned make_odd(T& val)
- {
- unsigned r = 0;
- while(!(val & 1u))
- {
- val >>= 1;
- ++r;
- }
- return r;
- }
- inline static bool less(const T& a, const T& b)
- {
- return a < b;
- }
-
- enum method_type
- {
- method_euclid = 0,
- method_binary = 1,
- method_mixed = 2,
- };
-
- static const method_type method =
- boost::has_right_shift_assign<T>::value && boost::has_left_shift_assign<T>::value && boost::has_less<T>::value && boost::has_modulus<T>::value
- ? method_mixed :
- boost::has_right_shift_assign<T>::value && boost::has_left_shift_assign<T>::value && boost::has_less<T>::value
- ? method_binary : method_euclid;
- };
- //
- // Default gcd_traits just inherits from defaults:
- //
- template <class T>
- struct gcd_traits : public gcd_traits_defaults<T> {};
- //
- // Special handling for polynomials:
- //
- namespace tools {
- template <class T>
- class polynomial;
- }
-
- template <class T>
- struct gcd_traits<boost::math::tools::polynomial<T> > : public gcd_traits_defaults<T>
- {
- static const boost::math::tools::polynomial<T>& abs(const boost::math::tools::polynomial<T>& val) { return val; }
- };
- //
- // Some platforms have fast bitscan operations, that allow us to implement
- // make_odd much more efficiently:
- //
-#if (defined(BOOST_MSVC) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
-#pragma intrinsic(_BitScanForward,)
- template <>
- struct gcd_traits<unsigned long> : public gcd_traits_defaults<unsigned long>
- {
- BOOST_FORCEINLINE static unsigned find_lsb(unsigned long val)
- {
- unsigned long result;
- _BitScanForward(&result, val);
- return result;
- }
- BOOST_FORCEINLINE static unsigned make_odd(unsigned long& val)
- {
- unsigned result = find_lsb(val);
- val >>= result;
- return result;
- }
- };
-
-#ifdef _M_X64
-#pragma intrinsic(_BitScanForward64)
- template <>
- struct gcd_traits<unsigned __int64> : public gcd_traits_defaults<unsigned __int64>
- {
- BOOST_FORCEINLINE static unsigned find_lsb(unsigned __int64 mask)
- {
- unsigned long result;
- _BitScanForward64(&result, mask);
- return result;
- }
- BOOST_FORCEINLINE static unsigned make_odd(unsigned __int64& val)
- {
- unsigned result = find_lsb(val);
- val >>= result;
- return result;
- }
- };
-#endif
- //
- // Other integer type are trivial adaptations of the above,
- // this works for signed types too, as by the time these functions
- // are called, all values are > 0.
- //
- template <> struct gcd_traits<long> : public gcd_traits_defaults<long>
- { BOOST_FORCEINLINE static unsigned make_odd(long& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
- template <> struct gcd_traits<unsigned int> : public gcd_traits_defaults<unsigned int>
- { BOOST_FORCEINLINE static unsigned make_odd(unsigned int& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
- template <> struct gcd_traits<int> : public gcd_traits_defaults<int>
- { BOOST_FORCEINLINE static unsigned make_odd(int& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
- template <> struct gcd_traits<unsigned short> : public gcd_traits_defaults<unsigned short>
- { BOOST_FORCEINLINE static unsigned make_odd(unsigned short& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
- template <> struct gcd_traits<short> : public gcd_traits_defaults<short>
- { BOOST_FORCEINLINE static unsigned make_odd(short& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
- template <> struct gcd_traits<unsigned char> : public gcd_traits_defaults<unsigned char>
- { BOOST_FORCEINLINE static unsigned make_odd(unsigned char& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
- template <> struct gcd_traits<signed char> : public gcd_traits_defaults<signed char>
- { BOOST_FORCEINLINE static signed make_odd(signed char& val){ signed result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
- template <> struct gcd_traits<char> : public gcd_traits_defaults<char>
- { BOOST_FORCEINLINE static unsigned make_odd(char& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
- template <> struct gcd_traits<wchar_t> : public gcd_traits_defaults<wchar_t>
- { BOOST_FORCEINLINE static unsigned make_odd(wchar_t& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
-#ifdef _M_X64
- template <> struct gcd_traits<__int64> : public gcd_traits_defaults<__int64>
- { BOOST_FORCEINLINE static unsigned make_odd(__int64& val){ unsigned result = gcd_traits<unsigned __int64>::find_lsb(val); val >>= result; return result; } };
-#endif
+ using boost::integer::gcd;
+ using boost::integer::lcm;
+ using boost::integer::gcd_range;
+ using boost::integer::lcm_range;
+ using boost::integer::gcd_evaluator;
+ using boost::integer::lcm_evaluator;
-#elif defined(BOOST_GCC) || defined(__clang__) || (defined(BOOST_INTEL) && defined(__GNUC__))
-
- template <>
- struct gcd_traits<unsigned> : public gcd_traits_defaults<unsigned>
- {
- BOOST_FORCEINLINE static unsigned find_lsb(unsigned mask)
- {
- return __builtin_ctz(mask);
- }
- BOOST_FORCEINLINE static unsigned make_odd(unsigned& val)
- {
- unsigned result = find_lsb(val);
- val >>= result;
- return result;
- }
- };
- template <>
- struct gcd_traits<unsigned long> : public gcd_traits_defaults<unsigned long>
- {
- BOOST_FORCEINLINE static unsigned find_lsb(unsigned long mask)
- {
- return __builtin_ctzl(mask);
- }
- BOOST_FORCEINLINE static unsigned make_odd(unsigned long& val)
- {
- unsigned result = find_lsb(val);
- val >>= result;
- return result;
- }
- };
- template <>
- struct gcd_traits<boost::ulong_long_type> : public gcd_traits_defaults<boost::ulong_long_type>
- {
- BOOST_FORCEINLINE static unsigned find_lsb(boost::ulong_long_type mask)
- {
- return __builtin_ctzll(mask);
- }
- BOOST_FORCEINLINE static unsigned make_odd(boost::ulong_long_type& val)
- {
- unsigned result = find_lsb(val);
- val >>= result;
- return result;
- }
- };
- //
- // Other integer type are trivial adaptations of the above,
- // this works for signed types too, as by the time these functions
- // are called, all values are > 0.
- //
- template <> struct gcd_traits<boost::long_long_type> : public gcd_traits_defaults<boost::long_long_type>
- {
- BOOST_FORCEINLINE static unsigned make_odd(boost::long_long_type& val) { unsigned result = gcd_traits<boost::ulong_long_type>::find_lsb(val); val >>= result; return result; }
- };
- template <> struct gcd_traits<long> : public gcd_traits_defaults<long>
- {
- BOOST_FORCEINLINE static unsigned make_odd(long& val) { unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; }
- };
- template <> struct gcd_traits<int> : public gcd_traits_defaults<int>
- {
- BOOST_FORCEINLINE static unsigned make_odd(int& val) { unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; }
- };
- template <> struct gcd_traits<unsigned short> : public gcd_traits_defaults<unsigned short>
- {
- BOOST_FORCEINLINE static unsigned make_odd(unsigned short& val) { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
- };
- template <> struct gcd_traits<short> : public gcd_traits_defaults<short>
- {
- BOOST_FORCEINLINE static unsigned make_odd(short& val) { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
- };
- template <> struct gcd_traits<unsigned char> : public gcd_traits_defaults<unsigned char>
- {
- BOOST_FORCEINLINE static unsigned make_odd(unsigned char& val) { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
- };
- template <> struct gcd_traits<signed char> : public gcd_traits_defaults<signed char>
- {
- BOOST_FORCEINLINE static signed make_odd(signed char& val) { signed result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
- };
- template <> struct gcd_traits<char> : public gcd_traits_defaults<char>
- {
- BOOST_FORCEINLINE static unsigned make_odd(char& val) { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
- };
- template <> struct gcd_traits<wchar_t> : public gcd_traits_defaults<wchar_t>
- {
- BOOST_FORCEINLINE static unsigned make_odd(wchar_t& val) { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
- };
-#endif
-
-namespace detail
-{
-
- //
- // The Mixed Binary Euclid Algorithm
- // Sidi Mohamed Sedjelmaci
- // Electronic Notes in Discrete Mathematics 35 (2009) 169-176
- //
- template <class T>
- T mixed_binary_gcd(T u, T v)
- {
- using std::swap;
- if(gcd_traits<T>::less(u, v))
- swap(u, v);
-
- unsigned shifts = 0;
-
- if(!u)
- return v;
- if(!v)
- return u;
-
- shifts = (std::min)(gcd_traits<T>::make_odd(u), gcd_traits<T>::make_odd(v));
-
- while(gcd_traits<T>::less(1, v))
- {
- u %= v;
- v -= u;
- if(!u)
- return v << shifts;
- if(!v)
- return u << shifts;
- gcd_traits<T>::make_odd(u);
- gcd_traits<T>::make_odd(v);
- if(gcd_traits<T>::less(u, v))
- swap(u, v);
- }
- return (v == 1 ? v : u) << shifts;
}
-
- /** Stein gcd (aka 'binary gcd')
- *
- * From Mathematics to Generic Programming, Alexander Stepanov, Daniel Rose
- */
- template <typename SteinDomain>
- SteinDomain Stein_gcd(SteinDomain m, SteinDomain n)
- {
- using std::swap;
- BOOST_ASSERT(m >= 0);
- BOOST_ASSERT(n >= 0);
- if (m == SteinDomain(0))
- return n;
- if (n == SteinDomain(0))
- return m;
- // m > 0 && n > 0
- int d_m = gcd_traits<SteinDomain>::make_odd(m);
- int d_n = gcd_traits<SteinDomain>::make_odd(n);
- // odd(m) && odd(n)
- while (m != n)
- {
- if (n > m)
- swap(n, m);
- m -= n;
- gcd_traits<SteinDomain>::make_odd(m);
- }
- // m == n
- m <<= (std::min)(d_m, d_n);
- return m;
- }
-
-
- /** Euclidean algorithm
- *
- * From Mathematics to Generic Programming, Alexander Stepanov, Daniel Rose
- *
- */
- template <typename EuclideanDomain>
- inline EuclideanDomain Euclid_gcd(EuclideanDomain a, EuclideanDomain b)
- {
- using std::swap;
- while (b != EuclideanDomain(0))
- {
- a %= b;
- swap(a, b);
- }
- return a;
- }
-
-
- template <typename T>
- inline BOOST_DEDUCED_TYPENAME enable_if_c<gcd_traits<T>::method == gcd_traits<T>::method_mixed, T>::type
- optimal_gcd_select(T const &a, T const &b)
- {
- return detail::mixed_binary_gcd(a, b);
- }
-
- template <typename T>
- inline BOOST_DEDUCED_TYPENAME enable_if_c<gcd_traits<T>::method == gcd_traits<T>::method_binary, T>::type
- optimal_gcd_select(T const &a, T const &b)
- {
- return detail::Stein_gcd(a, b);
- }
-
- template <typename T>
- inline BOOST_DEDUCED_TYPENAME enable_if_c<gcd_traits<T>::method == gcd_traits<T>::method_euclid, T>::type
- optimal_gcd_select(T const &a, T const &b)
- {
- return detail::Euclid_gcd(a, b);
- }
-
- template <class T>
- inline T lcm_imp(const T& a, const T& b)
- {
- T temp = boost::math::detail::optimal_gcd_select(a, b);
-#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40500)
- return (temp != T(0)) ? T(a / temp * b) : T(0);
-#else
- return temp ? T(a / temp * b) : T(0);
-#endif
- }
-
-} // namespace detail
-
-
-template <typename Integer>
-inline Integer gcd(Integer const &a, Integer const &b)
-{
- return detail::optimal_gcd_select(static_cast<Integer>(gcd_traits<Integer>::abs(a)), static_cast<Integer>(gcd_traits<Integer>::abs(b)));
-}
-
-template <typename Integer>
-inline Integer lcm(Integer const &a, Integer const &b)
-{
- return detail::lcm_imp(static_cast<Integer>(gcd_traits<Integer>::abs(a)), static_cast<Integer>(gcd_traits<Integer>::abs(b)));
}
-/**
- * Knuth, The Art of Computer Programming: Volume 2, Third edition, 1998
- * Chapter 4.5.2, Algorithm C: Greatest common divisor of n integers.
- *
- * Knuth counts down from n to zero but we naturally go from first to last.
- * We also return the termination position because it might be useful to know.
- *
- * Partly by quirk, partly by design, this algorithm is defined for n = 1,
- * because the gcd of {x} is x. It is not defined for n = 0.
- *
- * @tparam I Input iterator.
- * @return The gcd of the range and the iterator position at termination.
- */
-template <typename I>
-std::pair<typename std::iterator_traits<I>::value_type, I>
-gcd_range(I first, I last)
-{
- BOOST_ASSERT(first != last);
- typedef typename std::iterator_traits<I>::value_type T;
-
- T d = *first++;
- while (d != T(1) && first != last)
- {
- d = gcd(d, *first);
- first++;
- }
- return std::make_pair(d, first);
-}
-
-} // namespace math
-} // namespace boost
-
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
-
#endif // BOOST_MATH_COMMON_FACTOR_RT_HPP
diff --git a/boost/math/concepts/std_real_concept.hpp b/boost/math/concepts/std_real_concept.hpp
index b297501d98..b8657bc6a3 100644
--- a/boost/math/concepts/std_real_concept.hpp
+++ b/boost/math/concepts/std_real_concept.hpp
@@ -399,7 +399,3 @@ using concepts::llround;
} // namespace boost
#endif // BOOST_MATH_STD_REAL_CONCEPT_HPP
-
-
-
-
diff --git a/boost/math/constants/constants.hpp b/boost/math/constants/constants.hpp
index b5db9cedf7..8c5c4105d4 100644
--- a/boost/math/constants/constants.hpp
+++ b/boost/math/constants/constants.hpp
@@ -266,6 +266,7 @@ namespace boost{ namespace math
BOOST_DEFINE_MATH_CONSTANT(third, 3.333333333333333333333333333333333333e-01, "3.33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333e-01")
BOOST_DEFINE_MATH_CONSTANT(twothirds, 6.666666666666666666666666666666666666e-01, "6.66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667e-01")
BOOST_DEFINE_MATH_CONSTANT(two_thirds, 6.666666666666666666666666666666666666e-01, "6.66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667e-01")
+ BOOST_DEFINE_MATH_CONSTANT(sixth, 1.66666666666666666666666666666666666666666e-01, "1.66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667e-01")
BOOST_DEFINE_MATH_CONSTANT(three_quarters, 7.500000000000000000000000000000000000e-01, "7.50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-01")
BOOST_DEFINE_MATH_CONSTANT(root_two, 1.414213562373095048801688724209698078e+00, "1.41421356237309504880168872420969807856967187537694807317667973799073247846210703885038753432764157273501384623e+00")
BOOST_DEFINE_MATH_CONSTANT(root_three, 1.732050807568877293527446341505872366e+00, "1.73205080756887729352744634150587236694280525381038062805580697945193301690880003708114618675724857567562614142e+00")
@@ -343,5 +344,3 @@ namespace boost{ namespace math
#include <boost/math/constants/calculate_constants.hpp>
#endif // BOOST_MATH_CONSTANTS_CONSTANTS_INCLUDED
-
-
diff --git a/boost/math/interpolators/barycentric_rational.hpp b/boost/math/interpolators/barycentric_rational.hpp
new file mode 100644
index 0000000000..79bab9042d
--- /dev/null
+++ b/boost/math/interpolators/barycentric_rational.hpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright Nick Thompson, 2017
+ * 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)
+ *
+ * Given N samples (t_i, y_i) which are irregularly spaced, this routine constructs an
+ * interpolant s which is constructed in O(N) time, occupies O(N) space, and can be evaluated in O(N) time.
+ * The interpolation is stable, unless one point is incredibly close to another, and the next point is incredibly far.
+ * The measure of this stability is the "local mesh ratio", which can be queried from the routine.
+ * Pictorially, the following t_i spacing is bad (has a high local mesh ratio)
+ * || | | | |
+ * and this t_i spacing is good (has a low local mesh ratio)
+ * | | | | | | | | | |
+ *
+ *
+ * If f is C^{d+2}, then the interpolant is O(h^(d+1)) accurate, where d is the interpolation order.
+ * A disadvantage of this interpolant is that it does not reproduce rational functions; for example, 1/(1+x^2) is not interpolated exactly.
+ *
+ * References:
+ * Floater, Michael S., and Kai Hormann. "Barycentric rational interpolation with no poles and high rates of approximation." Numerische Mathematik 107.2 (2007): 315-331.
+ * Press, William H., et al. "Numerical recipes third edition: the art of scientific computing." Cambridge University Press 32 (2007): 10013-2473.
+ */
+
+#ifndef BOOST_MATH_INTERPOLATORS_BARYCENTRIC_RATIONAL_HPP
+#define BOOST_MATH_INTERPOLATORS_BARYCENTRIC_RATIONAL_HPP
+
+#include <memory>
+#include <boost/math/interpolators/detail/barycentric_rational_detail.hpp>
+
+namespace boost{ namespace math{
+
+template<class Real>
+class barycentric_rational
+{
+public:
+ barycentric_rational(const Real* const x, const Real* const y, size_t n, size_t approximation_order = 3);
+
+ template <class InputIterator1, class InputIterator2>
+ barycentric_rational(InputIterator1 start_x, InputIterator1 end_x, InputIterator2 start_y, size_t approximation_order = 3, typename boost::disable_if_c<boost::is_integral<InputIterator2>::value>::type* = 0);
+
+ Real operator()(Real x) const;
+
+private:
+ std::shared_ptr<detail::barycentric_rational_imp<Real>> m_imp;
+};
+
+template <class Real>
+barycentric_rational<Real>::barycentric_rational(const Real* const x, const Real* const y, size_t n, size_t approximation_order):
+ m_imp(std::make_shared<detail::barycentric_rational_imp<Real>>(x, x + n, y, approximation_order))
+{
+ return;
+}
+
+template <class Real>
+template <class InputIterator1, class InputIterator2>
+barycentric_rational<Real>::barycentric_rational(InputIterator1 start_x, InputIterator1 end_x, InputIterator2 start_y, size_t approximation_order, typename boost::disable_if_c<boost::is_integral<InputIterator2>::value>::type*)
+ : m_imp(std::make_shared<detail::barycentric_rational_imp<Real>>(start_x, end_x, start_y, approximation_order))
+{
+}
+
+template<class Real>
+Real barycentric_rational<Real>::operator()(Real x) const
+{
+ return m_imp->operator()(x);
+}
+
+
+}}
+#endif
diff --git a/boost/math/interpolators/cubic_b_spline.hpp b/boost/math/interpolators/cubic_b_spline.hpp
new file mode 100644
index 0000000000..73ac1d0137
--- /dev/null
+++ b/boost/math/interpolators/cubic_b_spline.hpp
@@ -0,0 +1,78 @@
+// Copyright Nick Thompson, 2017
+// 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 implements the compactly supported cubic b spline algorithm described in
+// Kress, Rainer. "Numerical analysis, volume 181 of Graduate Texts in Mathematics." (1998).
+// Splines of compact support are faster to evaluate and are better conditioned than classical cubic splines.
+
+// Let f be the function we are trying to interpolate, and s be the interpolating spline.
+// The routine constructs the interpolant in O(N) time, and evaluating s at a point takes constant time.
+// The order of accuracy depends on the regularity of the f, however, assuming f is
+// four-times continuously differentiable, the error is of O(h^4).
+// In addition, we can differentiate the spline and obtain a good interpolant for f'.
+// The main restriction of this method is that the samples of f must be evenly spaced.
+// Look for barycentric rational interpolation for non-evenly sampled data.
+// Properties:
+// - s(x_j) = f(x_j)
+// - All cubic polynomials interpolated exactly
+
+#ifndef BOOST_MATH_INTERPOLATORS_CUBIC_B_SPLINE_HPP
+#define BOOST_MATH_INTERPOLATORS_CUBIC_B_SPLINE_HPP
+
+#include <boost/math/interpolators/detail/cubic_b_spline_detail.hpp>
+
+namespace boost{ namespace math{
+
+template <class Real>
+class cubic_b_spline
+{
+public:
+ // If you don't know the value of the derivative at the endpoints, leave them as nans and the routine will estimate them.
+ // f[0] = f(a), f[length -1] = b, step_size = (b - a)/(length -1).
+ template <class BidiIterator>
+ cubic_b_spline(const BidiIterator f, BidiIterator end_p, Real left_endpoint, Real step_size,
+ Real left_endpoint_derivative = std::numeric_limits<Real>::quiet_NaN(),
+ Real right_endpoint_derivative = std::numeric_limits<Real>::quiet_NaN());
+ cubic_b_spline(const Real* const f, size_t length, Real left_endpoint, Real step_size,
+ Real left_endpoint_derivative = std::numeric_limits<Real>::quiet_NaN(),
+ Real right_endpoint_derivative = std::numeric_limits<Real>::quiet_NaN());
+
+ cubic_b_spline() = default;
+ Real operator()(Real x) const;
+
+ Real prime(Real x) const;
+
+private:
+ std::shared_ptr<detail::cubic_b_spline_imp<Real>> m_imp;
+};
+
+template<class Real>
+cubic_b_spline<Real>::cubic_b_spline(const Real* const f, size_t length, Real left_endpoint, Real step_size,
+ Real left_endpoint_derivative, Real right_endpoint_derivative) : m_imp(std::make_shared<detail::cubic_b_spline_imp<Real>>(f, f + length, left_endpoint, step_size, left_endpoint_derivative, right_endpoint_derivative))
+{
+}
+
+template <class Real>
+template <class BidiIterator>
+cubic_b_spline<Real>::cubic_b_spline(BidiIterator f, BidiIterator end_p, Real left_endpoint, Real step_size,
+ Real left_endpoint_derivative, Real right_endpoint_derivative) : m_imp(std::make_shared<detail::cubic_b_spline_imp<Real>>(f, end_p, left_endpoint, step_size, left_endpoint_derivative, right_endpoint_derivative))
+{
+}
+
+template<class Real>
+Real cubic_b_spline<Real>::operator()(Real x) const
+{
+ return m_imp->operator()(x);
+}
+
+template<class Real>
+Real cubic_b_spline<Real>::prime(Real x) const
+{
+ return m_imp->prime(x);
+}
+
+}}
+#endif
diff --git a/boost/math/interpolators/detail/barycentric_rational_detail.hpp b/boost/math/interpolators/detail/barycentric_rational_detail.hpp
new file mode 100644
index 0000000000..b853901d89
--- /dev/null
+++ b/boost/math/interpolators/detail/barycentric_rational_detail.hpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright Nick Thompson, 2017
+ * 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_MATH_INTERPOLATORS_BARYCENTRIC_RATIONAL_DETAIL_HPP
+#define BOOST_MATH_INTERPOLATORS_BARYCENTRIC_RATIONAL_DETAIL_HPP
+
+#include <vector>
+#include <boost/lexical_cast.hpp>
+#include <boost/math/special_functions/fpclassify.hpp>
+#include <boost/core/demangle.hpp>
+
+namespace boost{ namespace math{ namespace detail{
+
+template<class Real>
+class barycentric_rational_imp
+{
+public:
+ template <class InputIterator1, class InputIterator2>
+ barycentric_rational_imp(InputIterator1 start_x, InputIterator1 end_x, InputIterator2 start_y, size_t approximation_order = 3);
+
+ Real operator()(Real x) const;
+
+ // The barycentric weights are not really that interesting; except to the unit tests!
+ Real weight(size_t i) const { return m_w[i]; }
+
+private:
+ // Technically, we do not need to copy over y to m_y, or x to m_x.
+ // We could simply store a pointer. However, in doing so,
+ // we'd need to make sure the user managed the lifetime of m_y,
+ // and didn't alter its data. Since we are unlikely to run out of
+ // memory for a linearly scaling algorithm, it seems best just to make a copy.
+ std::vector<Real> m_y;
+ std::vector<Real> m_x;
+ std::vector<Real> m_w;
+};
+
+template <class Real>
+template <class InputIterator1, class InputIterator2>
+barycentric_rational_imp<Real>::barycentric_rational_imp(InputIterator1 start_x, InputIterator1 end_x, InputIterator2 start_y, size_t approximation_order)
+{
+ using std::abs;
+
+ std::ptrdiff_t n = std::distance(start_x, end_x);
+
+ if (approximation_order >= (std::size_t)n)
+ {
+ throw std::domain_error("Approximation order must be < data length.");
+ }
+
+ // Big sad memcpy to make sure the object is easy to use.
+ m_x.resize(n);
+ m_y.resize(n);
+ for(unsigned i = 0; start_x != end_x; ++start_x, ++start_y, ++i)
+ {
+ // But if we're going to do a memcpy, we can do some error checking which is inexpensive relative to the copy:
+ if(boost::math::isnan(*start_x))
+ {
+ std::string msg = std::string("x[") + boost::lexical_cast<std::string>(i) + "] is a NAN";
+ throw std::domain_error(msg);
+ }
+
+ if(boost::math::isnan(*start_y))
+ {
+ std::string msg = std::string("y[") + boost::lexical_cast<std::string>(i) + "] is a NAN";
+ throw std::domain_error(msg);
+ }
+
+ m_x[i] = *start_x;
+ m_y[i] = *start_y;
+ }
+
+ m_w.resize(n, 0);
+ for(int64_t k = 0; k < n; ++k)
+ {
+ int64_t i_min = (std::max)(k - (int64_t) approximation_order, (int64_t) 0);
+ int64_t i_max = k;
+ if (k >= n - (std::ptrdiff_t)approximation_order)
+ {
+ i_max = n - approximation_order - 1;
+ }
+
+ for(int64_t i = i_min; i <= i_max; ++i)
+ {
+ Real inv_product = 1;
+ int64_t j_max = (std::min)(static_cast<int64_t>(i + approximation_order), static_cast<int64_t>(n - 1));
+ for(int64_t j = i; j <= j_max; ++j)
+ {
+ if (j == k)
+ {
+ continue;
+ }
+
+ Real diff = m_x[k] - m_x[j];
+ if (abs(diff) < std::numeric_limits<Real>::epsilon())
+ {
+ std::string msg = std::string("Spacing between x[")
+ + boost::lexical_cast<std::string>(k) + std::string("] and x[")
+ + boost::lexical_cast<std::string>(i) + std::string("] is ")
+ + boost::lexical_cast<std::string>(diff) + std::string(", which is smaller than the epsilon of ")
+ + boost::core::demangle(typeid(Real).name());
+ throw std::logic_error(msg);
+ }
+ inv_product *= diff;
+ }
+ if (i % 2 == 0)
+ {
+ m_w[k] += 1/inv_product;
+ }
+ else
+ {
+ m_w[k] -= 1/inv_product;
+ }
+ }
+ }
+}
+
+template<class Real>
+Real barycentric_rational_imp<Real>::operator()(Real x) const
+{
+ Real numerator = 0;
+ Real denominator = 0;
+ for(size_t i = 0; i < m_x.size(); ++i)
+ {
+ // Presumably we should see if the accuracy is improved by using ULP distance of say, 5 here, instead of testing for floating point equality.
+ // However, it has been shown that if x approx x_i, but x != x_i, then inaccuracy in the numerator cancels the inaccuracy in the denominator,
+ // and the result is fairly accurate. See: http://epubs.siam.org/doi/pdf/10.1137/S0036144502417715
+ if (x == m_x[i])
+ {
+ return m_y[i];
+ }
+ Real t = m_w[i]/(x - m_x[i]);
+ numerator += t*m_y[i];
+ denominator += t;
+ }
+ return numerator/denominator;
+}
+
+/*
+ * A formula for computing the derivative of the barycentric representation is given in
+ * "Some New Aspects of Rational Interpolation", by Claus Schneider and Wilhelm Werner,
+ * Mathematics of Computation, v47, number 175, 1986.
+ * http://www.ams.org/journals/mcom/1986-47-175/S0025-5718-1986-0842136-8/S0025-5718-1986-0842136-8.pdf
+ * However, this requires a lot of machinery which is not built into the library at present.
+ * So we wait until there is a requirement to interpolate the derivative.
+ */
+}}}
+#endif
diff --git a/boost/math/interpolators/detail/cubic_b_spline_detail.hpp b/boost/math/interpolators/detail/cubic_b_spline_detail.hpp
new file mode 100644
index 0000000000..f7b2d6cd29
--- /dev/null
+++ b/boost/math/interpolators/detail/cubic_b_spline_detail.hpp
@@ -0,0 +1,287 @@
+// Copyright Nick Thompson, 2017
+// 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 CUBIC_B_SPLINE_DETAIL_HPP
+#define CUBIC_B_SPLINE_DETAIL_HPP
+
+#include <limits>
+#include <cmath>
+#include <vector>
+#include <memory>
+#include <boost/math/constants/constants.hpp>
+#include <boost/math/special_functions/fpclassify.hpp>
+
+namespace boost{ namespace math{ namespace detail{
+
+
+template <class Real>
+class cubic_b_spline_imp
+{
+public:
+ // If you don't know the value of the derivative at the endpoints, leave them as nans and the routine will estimate them.
+ // f[0] = f(a), f[length -1] = b, step_size = (b - a)/(length -1).
+ template <class BidiIterator>
+ cubic_b_spline_imp(BidiIterator f, BidiIterator end_p, Real left_endpoint, Real step_size,
+ Real left_endpoint_derivative = std::numeric_limits<Real>::quiet_NaN(),
+ Real right_endpoint_derivative = std::numeric_limits<Real>::quiet_NaN());
+
+ Real operator()(Real x) const;
+
+ Real prime(Real x) const;
+
+private:
+ std::vector<Real> m_beta;
+ Real m_h_inv;
+ Real m_a;
+ Real m_avg;
+};
+
+
+
+template <class Real>
+Real b3_spline(Real x)
+{
+ using std::abs;
+ Real absx = abs(x);
+ if (absx < 1)
+ {
+ Real y = 2 - absx;
+ Real z = 1 - absx;
+ return boost::math::constants::sixth<Real>()*(y*y*y - 4*z*z*z);
+ }
+ if (absx < 2)
+ {
+ Real y = 2 - absx;
+ return boost::math::constants::sixth<Real>()*y*y*y;
+ }
+ return (Real) 0;
+}
+
+template<class Real>
+Real b3_spline_prime(Real x)
+{
+ if (x < 0)
+ {
+ return -b3_spline_prime(-x);
+ }
+
+ if (x < 1)
+ {
+ return x*(3*boost::math::constants::half<Real>()*x - 2);
+ }
+ if (x < 2)
+ {
+ return -boost::math::constants::half<Real>()*(2 - x)*(2 - x);
+ }
+ return (Real) 0;
+}
+
+
+template <class Real>
+template <class BidiIterator>
+cubic_b_spline_imp<Real>::cubic_b_spline_imp(BidiIterator f, BidiIterator end_p, Real left_endpoint, Real step_size,
+ Real left_endpoint_derivative, Real right_endpoint_derivative) : m_a(left_endpoint), m_avg(0)
+{
+ using boost::math::constants::third;
+
+ std::size_t length = end_p - f;
+
+ if (length < 5)
+ {
+ if (boost::math::isnan(left_endpoint_derivative) || boost::math::isnan(right_endpoint_derivative))
+ {
+ throw std::logic_error("Interpolation using a cubic b spline with derivatives estimated at the endpoints requires at least 5 points.\n");
+ }
+ if (length < 3)
+ {
+ throw std::logic_error("Interpolation using a cubic b spline requires at least 3 points.\n");
+ }
+ }
+
+ if (boost::math::isnan(left_endpoint))
+ {
+ throw std::logic_error("Left endpoint is NAN; this is disallowed.\n");
+ }
+ if (left_endpoint + length*step_size >= (std::numeric_limits<Real>::max)())
+ {
+ throw std::logic_error("Right endpoint overflows the maximum representable number of the specified precision.\n");
+ }
+ if (step_size <= 0)
+ {
+ throw std::logic_error("The step size must be strictly > 0.\n");
+ }
+ // Storing the inverse of the stepsize does provide a measurable speedup.
+ // It's not huge, but nonetheless worthwhile.
+ m_h_inv = 1/step_size;
+
+ // Following Kress's notation, s'(a) = a1, s'(b) = b1
+ Real a1 = left_endpoint_derivative;
+ // See the finite-difference table on Wikipedia for reference on how
+ // to construct high-order estimates for one-sided derivatives:
+ // https://en.wikipedia.org/wiki/Finite_difference_coefficient#Forward_and_backward_finite_difference
+ // Here, we estimate then to O(h^4), as that is the maximum accuracy we could obtain from this method.
+ if (boost::math::isnan(a1))
+ {
+ // For simple functions (linear, quadratic, so on)
+ // almost all the error comes from derivative estimation.
+ // This does pairwise summation which gives us another digit of accuracy over naive summation.
+ Real t0 = 4*(f[1] + third<Real>()*f[3]);
+ Real t1 = -(25*third<Real>()*f[0] + f[4])/4 - 3*f[2];
+ a1 = m_h_inv*(t0 + t1);
+ }
+
+ Real b1 = right_endpoint_derivative;
+ if (boost::math::isnan(b1))
+ {
+ size_t n = length - 1;
+ Real t0 = 4*(f[n-3] + third<Real>()*f[n - 1]);
+ Real t1 = -(25*third<Real>()*f[n - 4] + f[n])/4 - 3*f[n - 2];
+
+ b1 = m_h_inv*(t0 + t1);
+ }
+
+ // s(x) = \sum \alpha_i B_{3}( (x- x_i - a)/h )
+ // Of course we must reindex from Kress's notation, since he uses negative indices which make C++ unhappy.
+ m_beta.resize(length + 2, std::numeric_limits<Real>::quiet_NaN());
+
+ // Since the splines have compact support, they decay to zero very fast outside the endpoints.
+ // This is often very annoying; we'd like to evaluate the interpolant a little bit outside the
+ // boundary [a,b] without massive error.
+ // A simple way to deal with this is just to subtract the DC component off the signal, so we need the average.
+ // This algorithm for computing the average is recommended in
+ // http://www.heikohoffmann.de/htmlthesis/node134.html
+ Real t = 1;
+ for (size_t i = 0; i < length; ++i)
+ {
+ if (boost::math::isnan(f[i]))
+ {
+ std::string err = "This function you are trying to interpolate is a nan at index " + std::to_string(i) + "\n";
+ throw std::logic_error(err);
+ }
+ m_avg += (f[i] - m_avg) / t;
+ t += 1;
+ }
+
+
+ // Now we must solve an almost-tridiagonal system, which requires O(N) operations.
+ // There are, in fact 5 diagonals, but they only differ from zero on the first and last row,
+ // so we can patch up the tridiagonal row reduction algorithm to deal with two special rows.
+ // See Kress, equations 8.41
+ // The the "tridiagonal" matrix is:
+ // 1 0 -1
+ // 1 4 1
+ // 1 4 1
+ // 1 4 1
+ // ....
+ // 1 4 1
+ // 1 0 -1
+ // Numerical estimate indicate that as N->Infinity, cond(A) -> 6.9, so this matrix is good.
+ std::vector<Real> rhs(length + 2, std::numeric_limits<Real>::quiet_NaN());
+ std::vector<Real> super_diagonal(length + 2, std::numeric_limits<Real>::quiet_NaN());
+
+ rhs[0] = -2*step_size*a1;
+ rhs[rhs.size() - 1] = -2*step_size*b1;
+
+ super_diagonal[0] = 0;
+
+ for(size_t i = 1; i < rhs.size() - 1; ++i)
+ {
+ rhs[i] = 6*(f[i - 1] - m_avg);
+ super_diagonal[i] = 1;
+ }
+
+
+ // One step of row reduction on the first row to patch up the 5-diagonal problem:
+ // 1 0 -1 | r0
+ // 1 4 1 | r1
+ // mapsto:
+ // 1 0 -1 | r0
+ // 0 4 2 | r1 - r0
+ // mapsto
+ // 1 0 -1 | r0
+ // 0 1 1/2| (r1 - r0)/4
+ super_diagonal[1] = 0.5;
+ rhs[1] = (rhs[1] - rhs[0])/4;
+
+ // Now do a tridiagonal row reduction the standard way, until just before the last row:
+ for (size_t i = 2; i < rhs.size() - 1; ++i)
+ {
+ Real diagonal = 4 - super_diagonal[i - 1];
+ rhs[i] = (rhs[i] - rhs[i - 1])/diagonal;
+ super_diagonal[i] /= diagonal;
+ }
+
+ // Now the last row, which is in the form
+ // 1 sd[n-3] 0 | rhs[n-3]
+ // 0 1 sd[n-2] | rhs[n-2]
+ // 1 0 -1 | rhs[n-1]
+ Real final_subdiag = -super_diagonal[rhs.size() - 3];
+ rhs[rhs.size() - 1] = (rhs[rhs.size() - 1] - rhs[rhs.size() - 3])/final_subdiag;
+ Real final_diag = -1/final_subdiag;
+ // Now we're here:
+ // 1 sd[n-3] 0 | rhs[n-3]
+ // 0 1 sd[n-2] | rhs[n-2]
+ // 0 1 final_diag | (rhs[n-1] - rhs[n-3])/diag
+
+ final_diag = final_diag - super_diagonal[rhs.size() - 2];
+ rhs[rhs.size() - 1] = rhs[rhs.size() - 1] - rhs[rhs.size() - 2];
+
+
+ // Back substitutions:
+ m_beta[rhs.size() - 1] = rhs[rhs.size() - 1]/final_diag;
+ for(size_t i = rhs.size() - 2; i > 0; --i)
+ {
+ m_beta[i] = rhs[i] - super_diagonal[i]*m_beta[i + 1];
+ }
+ m_beta[0] = m_beta[2] + rhs[0];
+}
+
+template<class Real>
+Real cubic_b_spline_imp<Real>::operator()(Real x) const
+{
+ // See Kress, 8.40: Since B3 has compact support, we don't have to sum over all terms,
+ // just the (at most 5) whose support overlaps the argument.
+ Real z = m_avg;
+ Real t = m_h_inv*(x - m_a) + 1;
+
+ using std::max;
+ using std::min;
+ using std::ceil;
+ using std::floor;
+
+ size_t k_min = (size_t) max(static_cast<long>(0), boost::math::ltrunc(ceil(t - 2)));
+ size_t k_max = (size_t) max(min(static_cast<long>(m_beta.size() - 1), boost::math::ltrunc(floor(t + 2))), (long) 0);
+ for (size_t k = k_min; k <= k_max; ++k)
+ {
+ z += m_beta[k]*b3_spline(t - k);
+ }
+
+ return z;
+}
+
+template<class Real>
+Real cubic_b_spline_imp<Real>::prime(Real x) const
+{
+ Real z = 0;
+ Real t = m_h_inv*(x - m_a) + 1;
+
+ using std::max;
+ using std::min;
+ using std::ceil;
+ using std::floor;
+
+ size_t k_min = (size_t) max(static_cast<long>(0), boost::math::ltrunc(ceil(t - 2)));
+ size_t k_max = (size_t) min(static_cast<long>(m_beta.size() - 1), boost::math::ltrunc(floor(t + 2)));
+
+ for (size_t k = k_min; k <= k_max; ++k)
+ {
+ z += m_beta[k]*b3_spline_prime(t - k);
+ }
+ return z*m_h_inv;
+}
+
+}}}
+#endif
diff --git a/boost/math/quadrature/trapezoidal.hpp b/boost/math/quadrature/trapezoidal.hpp
new file mode 100644
index 0000000000..af466a0916
--- /dev/null
+++ b/boost/math/quadrature/trapezoidal.hpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright Nick Thompson, 2017
+ * 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)
+ *
+ * Use the adaptive trapezoidal rule to estimate the integral of periodic functions over a period,
+ * or to integrate a function whose derivative vanishes at the endpoints.
+ *
+ * If your function does not satisfy these conditions, and instead is simply continuous and bounded
+ * over the whole interval, then this routine will still converge, albeit slowly. However, there
+ * are much more efficient methods in this case, including Romberg, Simpson, and double exponential quadrature.
+ */
+
+#ifndef BOOST_MATH_QUADRATURE_TRAPEZOIDAL_HPP
+#define BOOST_MATH_QUADRATURE_TRAPEZOIDAL_HPP
+
+#include <cmath>
+#include <limits>
+#include <stdexcept>
+#include <boost/math/constants/constants.hpp>
+#include <boost/math/special_functions/fpclassify.hpp>
+#include <boost/math/policies/error_handling.hpp>
+
+namespace boost{ namespace math{ namespace quadrature {
+
+template<class F, class Real, class Policy>
+Real trapezoidal(F f, Real a, Real b, Real tol, std::size_t max_refinements, Real* error_estimate, Real* L1, const Policy& pol)
+{
+ static const char* function = "boost::math::quadrature::trapezoidal<%1%>(F, %1%, %1%, %1%)";
+ using std::abs;
+ using boost::math::constants::half;
+ if(a >= b)
+ {
+ return boost::math::policies::raise_domain_error(function, "a < b for integration over the region [a, b] is required, but got a = %1%.\n", a, pol);
+ }
+ if (!(boost::math::isfinite)(a))
+ {
+ return boost::math::policies::raise_domain_error(function, "Left endpoint of integration must be finite for adaptive trapezoidal integration but got a = %1%.\n", a, pol);
+ }
+ if (!(boost::math::isfinite)(b))
+ {
+ return boost::math::policies::raise_domain_error(function, "Right endpoint of integration must be finite for adaptive trapedzoidal integration but got b = %1%.\n", b, pol);
+ }
+
+ Real ya = f(a);
+ Real yb = f(b);
+ Real h = (b - a)*half<Real>();
+ Real I0 = (ya + yb)*h;
+ Real IL0 = (abs(ya) + abs(yb))*h;
+
+ Real yh = f(a + h);
+ Real I1 = half<Real>()*I0 + yh*h;
+ Real IL1 = half<Real>()*IL0 + abs(yh)*h;
+
+ // The recursion is:
+ // I_k = 1/2 I_{k-1} + 1/2^k \sum_{j=1; j odd, j < 2^k} f(a + j(b-a)/2^k)
+ std::size_t k = 2;
+ // We want to go through at least 4 levels so we have sampled the function at least 10 times.
+ // Otherwise, we could terminate prematurely and miss essential features.
+ // This is of course possible anyway, but 10 samples seems to be a reasonable compromise.
+ Real error = abs(I0 - I1);
+ while (k < 4 || (k < max_refinements && error > tol*IL1) )
+ {
+ I0 = I1;
+ IL0 = IL1;
+
+ I1 = half<Real>()*I0;
+ IL1 = half<Real>()*IL0;
+ std::size_t p = static_cast<std::size_t>(1u) << k;
+ h *= half<Real>();
+ Real sum = 0;
+ Real absum = 0;
+
+ for(std::size_t j = 1; j < p; j += 2)
+ {
+ Real y = f(a + j*h);
+ sum += y;
+ absum += abs(y);
+ }
+
+ I1 += sum*h;
+ IL1 += absum*h;
+ ++k;
+ error = abs(I0 - I1);
+ }
+
+ if (error_estimate)
+ {
+ *error_estimate = error;
+ }
+
+ if (L1)
+ {
+ *L1 = IL1;
+ }
+
+ return I1;
+}
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1800)
+// Template argument dedcution failure otherwise:
+template<class F, class Real>
+Real trapezoidal(F f, Real a, Real b, Real tol = 0, std::size_t max_refinements = 10, Real* error_estimate = 0, Real* L1 = 0)
+#elif !defined(BOOST_NO_CXX11_NULLPTR)
+template<class F, class Real>
+Real trapezoidal(F f, Real a, Real b, Real tol = boost::math::tools::root_epsilon<Real>(), std::size_t max_refinements = 10, Real* error_estimate = nullptr, Real* L1 = nullptr)
+#else
+template<class F, class Real>
+Real trapezoidal(F f, Real a, Real b, Real tol = boost::math::tools::root_epsilon<Real>(), std::size_t max_refinements = 10, Real* error_estimate = 0, Real* L1 = 0)
+#endif
+{
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1600)
+ if (tol == 0)
+ tol = boost::math::tools::root_epsilon<Real>();
+#endif
+ return trapezoidal(f, a, b, tol, max_refinements, error_estimate, L1, boost::math::policies::policy<>());
+}
+
+}}}
+#endif
diff --git a/boost/math/special_functions/detail/airy_ai_bi_zero.hpp b/boost/math/special_functions/detail/airy_ai_bi_zero.hpp
index dbb7388dda..b5a71c78eb 100644
--- a/boost/math/special_functions/detail/airy_ai_bi_zero.hpp
+++ b/boost/math/special_functions/detail/airy_ai_bi_zero.hpp
@@ -86,7 +86,7 @@
class function_object_ai_and_ai_prime
{
public:
- function_object_ai_and_ai_prime(const Policy pol) : my_pol(pol) { }
+ function_object_ai_and_ai_prime(const Policy& pol) : my_pol(pol) { }
boost::math::tuple<T, T> operator()(const T& x) const
{
@@ -137,7 +137,7 @@
class function_object_bi_and_bi_prime
{
public:
- function_object_bi_and_bi_prime(const Policy pol) : my_pol(pol) { }
+ function_object_bi_and_bi_prime(const Policy& pol) : my_pol(pol) { }
boost::math::tuple<T, T> operator()(const T& x) const
{
diff --git a/boost/math/special_functions/detail/bessel_i0.hpp b/boost/math/special_functions/detail/bessel_i0.hpp
index 5896db8f76..7738229454 100644
--- a/boost/math/special_functions/detail/bessel_i0.hpp
+++ b/boost/math/special_functions/detail/bessel_i0.hpp
@@ -532,7 +532,7 @@ template <typename T>
inline T bessel_i0(const T& x)
{
typedef mpl::int_<
- std::numeric_limits<T>::digits == 0 ?
+ ((std::numeric_limits<T>::digits == 0) || (std::numeric_limits<T>::radix != 2)) ?
0 :
std::numeric_limits<T>::digits <= 24 ?
24 :
diff --git a/boost/math/special_functions/detail/bessel_i1.hpp b/boost/math/special_functions/detail/bessel_i1.hpp
index 0f9ba96bd8..a6364a6cc9 100644
--- a/boost/math/special_functions/detail/bessel_i1.hpp
+++ b/boost/math/special_functions/detail/bessel_i1.hpp
@@ -555,7 +555,7 @@ template <typename T>
inline T bessel_i1(const T& x)
{
typedef mpl::int_<
- std::numeric_limits<T>::digits == 0 ?
+ ((std::numeric_limits<T>::digits == 0) || (std::numeric_limits<T>::radix != 2)) ?
0 :
std::numeric_limits<T>::digits <= 24 ?
24 :
diff --git a/boost/math/special_functions/detail/bessel_k0.hpp b/boost/math/special_functions/detail/bessel_k0.hpp
index 4f3420ffc0..74f4014bd9 100644
--- a/boost/math/special_functions/detail/bessel_k0.hpp
+++ b/boost/math/special_functions/detail/bessel_k0.hpp
@@ -483,7 +483,7 @@ template <typename T>
inline T bessel_k0(const T& x)
{
typedef mpl::int_<
- std::numeric_limits<T>::digits == 0 ?
+ ((std::numeric_limits<T>::digits == 0) || (std::numeric_limits<T>::radix != 2)) ?
0 :
std::numeric_limits<T>::digits <= 24 ?
24 :
diff --git a/boost/math/special_functions/detail/bessel_k1.hpp b/boost/math/special_functions/detail/bessel_k1.hpp
index 0ae90056cb..2ab191fb49 100644
--- a/boost/math/special_functions/detail/bessel_k1.hpp
+++ b/boost/math/special_functions/detail/bessel_k1.hpp
@@ -525,7 +525,7 @@ namespace boost { namespace math { namespace detail{
inline T bessel_k1(const T& x)
{
typedef mpl::int_<
- std::numeric_limits<T>::digits == 0 ?
+ ((std::numeric_limits<T>::digits == 0) || (std::numeric_limits<T>::radix != 2)) ?
0 :
std::numeric_limits<T>::digits <= 24 ?
24 :
diff --git a/boost/math/special_functions/legendre.hpp b/boost/math/special_functions/legendre.hpp
index 1a2ef5d615..6028b377d3 100644
--- a/boost/math/special_functions/legendre.hpp
+++ b/boost/math/special_functions/legendre.hpp
@@ -11,8 +11,11 @@
#pragma once
#endif
+#include <utility>
+#include <vector>
#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/factorials.hpp>
+#include <boost/math/tools/roots.hpp>
#include <boost/math/tools/config.hpp>
namespace boost{
@@ -68,6 +71,149 @@ T legendre_imp(unsigned l, T x, const Policy& pol, bool second = false)
return p1;
}
+template <class T, class Policy>
+T legendre_p_prime_imp(unsigned l, T x, const Policy& pol, T* Pn
+#ifdef BOOST_NO_CXX11_NULLPTR
+ = 0
+#else
+ = nullptr
+#endif
+)
+{
+ static const char* function = "boost::math::legrendre_p_prime<%1%>(unsigned, %1%)";
+ // Error handling:
+ if ((x < -1) || (x > 1))
+ return policies::raise_domain_error<T>(
+ function,
+ "The Legendre Polynomial is defined for"
+ " -1 <= x <= 1, but got x = %1%.", x, pol);
+
+ if (l == 0)
+ {
+ if (Pn)
+ {
+ *Pn = 1;
+ }
+ return 0;
+ }
+ T p0 = 1;
+ T p1 = x;
+ T p_prime;
+ bool odd = l & 1;
+ // If the order is odd, we sum all the even polynomials:
+ if (odd)
+ {
+ p_prime = p0;
+ }
+ else // Otherwise we sum the odd polynomials * (2n+1)
+ {
+ p_prime = 3*p1;
+ }
+
+ unsigned n = 1;
+ while(n < l - 1)
+ {
+ std::swap(p0, p1);
+ p1 = boost::math::legendre_next(n, x, p0, p1);
+ ++n;
+ if (odd)
+ {
+ p_prime += (2*n+1)*p1;
+ odd = false;
+ }
+ else
+ {
+ odd = true;
+ }
+ }
+ // This allows us to evaluate the derivative and the function for the same cost.
+ if (Pn)
+ {
+ std::swap(p0, p1);
+ *Pn = boost::math::legendre_next(n, x, p0, p1);
+ }
+ return p_prime;
+}
+
+template <class T, class Policy>
+struct legendre_p_zero_func
+{
+ int n;
+ const Policy& pol;
+
+ legendre_p_zero_func(int n_, const Policy& p) : n(n_), pol(p) {}
+
+ std::pair<T, T> operator()(T x) const
+ {
+ T Pn;
+ T Pn_prime = detail::legendre_p_prime_imp(n, x, pol, &Pn);
+ return std::pair<T, T>(Pn, Pn_prime);
+ };
+};
+
+template <class T, class Policy>
+std::vector<T> legendre_p_zeros_imp(int n, const Policy& pol)
+{
+ using std::cos;
+ using std::sin;
+ using std::ceil;
+ using std::sqrt;
+ using boost::math::constants::pi;
+ using boost::math::constants::half;
+ using boost::math::tools::newton_raphson_iterate;
+
+ BOOST_ASSERT(n >= 0);
+ std::vector<T> zeros;
+ if (n == 0)
+ {
+ // There are no zeros of P_0(x) = 1.
+ return zeros;
+ }
+ int k;
+ if (n & 1)
+ {
+ zeros.resize((n-1)/2 + 1, std::numeric_limits<T>::quiet_NaN());
+ zeros[0] = 0;
+ k = 1;
+ }
+ else
+ {
+ zeros.resize(n/2, std::numeric_limits<T>::quiet_NaN());
+ k = 0;
+ }
+ T half_n = ceil(n*half<T>());
+
+ while (k < (int)zeros.size())
+ {
+ // Bracket the root: Szego:
+ // Gabriel Szego, Inequalities for the Zeros of Legendre Polynomials and Related Functions, Transactions of the American Mathematical Society, Vol. 39, No. 1 (1936)
+ T theta_nk = ((half_n - half<T>()*half<T>() - static_cast<T>(k))*pi<T>())/(static_cast<T>(n)+half<T>());
+ T lower_bound = cos( (half_n - static_cast<T>(k))*pi<T>()/static_cast<T>(n + 1));
+ T cos_nk = cos(theta_nk);
+ T upper_bound = cos_nk;
+ // First guess follows from:
+ // F. G. Tricomi, Sugli zeri dei polinomi sferici ed ultrasferici, Ann. Mat. Pura Appl., 31 (1950), pp. 93–97;
+ T inv_n_sq = 1/static_cast<T>(n*n);
+ T sin_nk = sin(theta_nk);
+ T x_nk_guess = (1 - inv_n_sq/static_cast<T>(8) + inv_n_sq /static_cast<T>(8*n) - (inv_n_sq*inv_n_sq/384)*(39 - 28 / (sin_nk*sin_nk) ) )*cos_nk;
+
+ boost::uintmax_t number_of_iterations = policies::get_max_root_iterations<Policy>();
+
+ legendre_p_zero_func<T, Policy> f(n, pol);
+
+ const T x_nk = newton_raphson_iterate(f, x_nk_guess,
+ lower_bound, upper_bound,
+ policies::digits<T, Policy>(),
+ number_of_iterations);
+
+ BOOST_ASSERT(lower_bound < x_nk);
+ BOOST_ASSERT(upper_bound > x_nk);
+ zeros[k] = x_nk;
+ ++k;
+ }
+ return zeros;
+}
+
} // namespace detail
template <class T, class Policy>
@@ -82,13 +228,49 @@ inline typename boost::enable_if_c<policies::is_policy<Policy>::value, typename
return policies::checked_narrowing_cast<result_type, Policy>(detail::legendre_imp(l, static_cast<value_type>(x), pol, false), function);
}
+
+template <class T, class Policy>
+inline typename boost::enable_if_c<policies::is_policy<Policy>::value, typename tools::promote_args<T>::type>::type
+ legendre_p_prime(int l, T x, const Policy& pol)
+{
+ typedef typename tools::promote_args<T>::type result_type;
+ typedef typename policies::evaluation<result_type, Policy>::type value_type;
+ static const char* function = "boost::math::legendre_p_prime<%1%>(unsigned, %1%)";
+ if(l < 0)
+ return policies::checked_narrowing_cast<result_type, Policy>(detail::legendre_p_prime_imp(-l-1, static_cast<value_type>(x), pol), function);
+ return policies::checked_narrowing_cast<result_type, Policy>(detail::legendre_p_prime_imp(l, static_cast<value_type>(x), pol), function);
+}
+
template <class T>
-inline typename tools::promote_args<T>::type
+inline typename tools::promote_args<T>::type
legendre_p(int l, T x)
{
return boost::math::legendre_p(l, x, policies::policy<>());
}
+template <class T>
+inline typename tools::promote_args<T>::type
+ legendre_p_prime(int l, T x)
+{
+ return boost::math::legendre_p_prime(l, x, policies::policy<>());
+}
+
+template <class T, class Policy>
+inline std::vector<T> legendre_p_zeros(int l, const Policy& pol)
+{
+ if(l < 0)
+ return detail::legendre_p_zeros_imp<T>(-l-1, pol);
+
+ return detail::legendre_p_zeros_imp<T>(l, pol);
+}
+
+
+template <class T>
+inline std::vector<T> legendre_p_zeros(int l)
+{
+ return boost::math::legendre_p_zeros<T>(l, policies::policy<>());
+}
+
template <class T, class Policy>
inline typename boost::enable_if_c<policies::is_policy<Policy>::value, typename tools::promote_args<T>::type>::type
legendre_q(unsigned l, T x, const Policy& pol)
@@ -99,7 +281,7 @@ inline typename boost::enable_if_c<policies::is_policy<Policy>::value, typename
}
template <class T>
-inline typename tools::promote_args<T>::type
+inline typename tools::promote_args<T>::type
legendre_q(unsigned l, T x)
{
return boost::math::legendre_q(l, x, policies::policy<>());
@@ -107,7 +289,7 @@ inline typename tools::promote_args<T>::type
// Recurrence for associated polynomials:
template <class T1, class T2, class T3>
-inline typename tools::promote_args<T1, T2, T3>::type
+inline typename tools::promote_args<T1, T2, T3>::type
legendre_next(unsigned l, unsigned m, T1 x, T2 Pl, T3 Plm1)
{
typedef typename tools::promote_args<T1, T2, T3>::type result_type;
@@ -189,6 +371,3 @@ inline typename tools::promote_args<T>::type
} // namespace boost
#endif // BOOST_MATH_SPECIAL_LEGENDRE_HPP
-
-
-
diff --git a/boost/math/special_functions/legendre_stieltjes.hpp b/boost/math/special_functions/legendre_stieltjes.hpp
new file mode 100644
index 0000000000..5d68198870
--- /dev/null
+++ b/boost/math/special_functions/legendre_stieltjes.hpp
@@ -0,0 +1,235 @@
+// Copyright Nick Thompson 2017.
+// 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_MATH_SPECIAL_LEGENDRE_STIELTJES_HPP
+#define BOOST_MATH_SPECIAL_LEGENDRE_STIELTJES_HPP
+
+/*
+ * Constructs the Legendre-Stieltjes polynomial of degree m.
+ * The Legendre-Stieltjes polynomials are used to create extensions for Gaussian quadratures,
+ * commonly called "Gauss-Konrod" quadratures.
+ *
+ * References:
+ * Patterson, TNL. "The optimum addition of points to quadrature formulae." Mathematics of Computation 22.104 (1968): 847-856.
+ */
+
+#include <iostream>
+#include <vector>
+#include <boost/math/tools/roots.hpp>
+#include <boost/math/special_functions/legendre.hpp>
+
+namespace boost{
+namespace math{
+
+template<class Real>
+class legendre_stieltjes
+{
+public:
+ legendre_stieltjes(size_t m)
+ {
+ if (m == 0)
+ {
+ throw std::domain_error("The Legendre-Stieltjes polynomial is defined for order m > 0.\n");
+ }
+ m_m = m;
+ std::ptrdiff_t n = m - 1;
+ std::ptrdiff_t q;
+ std::ptrdiff_t r;
+ bool odd = n & 1;
+ if (odd)
+ {
+ q = 1;
+ r = (n-1)/2 + 2;
+ }
+ else
+ {
+ q = 0;
+ r = n/2 + 1;
+ }
+ m_a.resize(r + 1);
+ // We'll keep the ones-based indexing at the cost of storing a superfluous element
+ // so that we can follow Patterson's notation exactly.
+ m_a[r] = static_cast<Real>(1);
+ // Make sure using the zero index is a bug:
+ m_a[0] = std::numeric_limits<Real>::quiet_NaN();
+
+ for (std::ptrdiff_t k = 1; k < r; ++k)
+ {
+ Real ratio = 1;
+ m_a[r - k] = 0;
+ for (std::ptrdiff_t i = r + 1 - k; i <= r; ++i)
+ {
+ // See Patterson, equation 12
+ std::ptrdiff_t num = (n - q + 2*(i + k - 1))*(n + q + 2*(k - i + 1))*(n-1-q+2*(i-k))*(2*(k+i-1) -1 -q -n);
+ std::ptrdiff_t den = (n - q + 2*(i - k))*(2*(k + i - 1) - q - n)*(n + 1 + q + 2*(k - i))*(n - 1 - q + 2*(i + k));
+ ratio *= static_cast<Real>(num)/static_cast<Real>(den);
+ m_a[r - k] -= ratio*m_a[i];
+ }
+ }
+ }
+
+
+ Real norm_sq() const
+ {
+ Real t = 0;
+ bool odd = m_m & 1;
+ for (size_t i = 1; i < m_a.size(); ++i)
+ {
+ if(odd)
+ {
+ t += 2*m_a[i]*m_a[i]/static_cast<Real>(4*i-1);
+ }
+ else
+ {
+ t += 2*m_a[i]*m_a[i]/static_cast<Real>(4*i-3);
+ }
+ }
+ return t;
+ }
+
+
+ Real operator()(Real x) const
+ {
+ // Trivial implementation:
+ // Em += m_a[i]*legendre_p(2*i - 1, x); m odd
+ // Em += m_a[i]*legendre_p(2*i - 2, x); m even
+ size_t r = m_a.size() - 1;
+ Real p0 = 1;
+ Real p1 = x;
+
+ Real Em;
+ bool odd = m_m & 1;
+ if (odd)
+ {
+ Em = m_a[1]*p1;
+ }
+ else
+ {
+ Em = m_a[1]*p0;
+ }
+
+ unsigned n = 1;
+ for (size_t i = 2; i <= r; ++i)
+ {
+ std::swap(p0, p1);
+ p1 = boost::math::legendre_next(n, x, p0, p1);
+ ++n;
+ if (!odd)
+ {
+ Em += m_a[i]*p1;
+ }
+ std::swap(p0, p1);
+ p1 = boost::math::legendre_next(n, x, p0, p1);
+ ++n;
+ if(odd)
+ {
+ Em += m_a[i]*p1;
+ }
+ }
+ return Em;
+ }
+
+
+ Real prime(Real x) const
+ {
+ Real Em_prime = 0;
+
+ for (size_t i = 1; i < m_a.size(); ++i)
+ {
+ if(m_m & 1)
+ {
+ Em_prime += m_a[i]*detail::legendre_p_prime_imp(2*i - 1, x, policies::policy<>());
+ }
+ else
+ {
+ Em_prime += m_a[i]*detail::legendre_p_prime_imp(2*i - 2, x, policies::policy<>());
+ }
+ }
+ return Em_prime;
+ }
+
+ std::vector<Real> zeros() const
+ {
+ using boost::math::constants::half;
+
+ std::vector<Real> stieltjes_zeros;
+ std::vector<Real> legendre_zeros = legendre_p_zeros<Real>(m_m - 1);
+ int k;
+ if (m_m & 1)
+ {
+ stieltjes_zeros.resize(legendre_zeros.size() + 1, std::numeric_limits<Real>::quiet_NaN());
+ stieltjes_zeros[0] = 0;
+ k = 1;
+ }
+ else
+ {
+ stieltjes_zeros.resize(legendre_zeros.size(), std::numeric_limits<Real>::quiet_NaN());
+ k = 0;
+ }
+
+ while (k < (int)stieltjes_zeros.size())
+ {
+ Real lower_bound;
+ Real upper_bound;
+ if (m_m & 1)
+ {
+ lower_bound = legendre_zeros[k - 1];
+ if (k == (int)legendre_zeros.size())
+ {
+ upper_bound = 1;
+ }
+ else
+ {
+ upper_bound = legendre_zeros[k];
+ }
+ }
+ else
+ {
+ lower_bound = legendre_zeros[k];
+ if (k == (int)legendre_zeros.size() - 1)
+ {
+ upper_bound = 1;
+ }
+ else
+ {
+ upper_bound = legendre_zeros[k+1];
+ }
+ }
+
+ // The root bracketing is not very tight; to keep weird stuff from happening
+ // in the Newton's method, let's tighten up the tolerance using a few bisections.
+ boost::math::tools::eps_tolerance<Real> tol(6);
+ auto g = [&](Real t) { return this->operator()(t); };
+ auto p = boost::math::tools::bisect(g, lower_bound, upper_bound, tol);
+
+ Real x_nk_guess = p.first + (p.second - p.first)*half<Real>();
+ boost::uintmax_t number_of_iterations = 500;
+
+ auto f = [&] (Real x) { Real Pn = this->operator()(x);
+ Real Pn_prime = this->prime(x);
+ return std::pair<Real, Real>(Pn, Pn_prime); };
+
+ const Real x_nk = boost::math::tools::newton_raphson_iterate(f, x_nk_guess,
+ p.first, p.second,
+ 2*std::numeric_limits<Real>::digits10,
+ number_of_iterations);
+
+ BOOST_ASSERT(p.first < x_nk);
+ BOOST_ASSERT(x_nk < p.second);
+ stieltjes_zeros[k] = x_nk;
+ ++k;
+ }
+ return stieltjes_zeros;
+ }
+
+private:
+ // Coefficients of Legendre expansion
+ std::vector<Real> m_a;
+ int m_m;
+};
+
+}}
+#endif
diff --git a/boost/math/special_functions/math_fwd.hpp b/boost/math/special_functions/math_fwd.hpp
index efb8f067ac..9becef9f6d 100644
--- a/boost/math/special_functions/math_fwd.hpp
+++ b/boost/math/special_functions/math_fwd.hpp
@@ -23,6 +23,7 @@
#pragma once
#endif
+#include <vector>
#include <boost/math/special_functions/detail/round_fwd.hpp>
#include <boost/math/tools/promotion.hpp> // for argument promotion.
#include <boost/math/policies/policy.hpp>
@@ -181,10 +182,24 @@ namespace boost
template <class T>
typename tools::promote_args<T>::type
legendre_p(int l, T x);
+ template <class T>
+ typename tools::promote_args<T>::type
+ legendre_p_prime(int l, T x);
+
+
+ template <class T, class Policy>
+ inline std::vector<T> legendre_p_zeros(int l, const Policy& pol);
+
+ template <class T>
+ inline std::vector<T> legendre_p_zeros(int l);
+
#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
template <class T, class Policy>
typename boost::enable_if_c<policies::is_policy<Policy>::value, typename tools::promote_args<T>::type>::type
legendre_p(int l, T x, const Policy& pol);
+ template <class T, class Policy>
+ inline typename boost::enable_if_c<policies::is_policy<Policy>::value, typename tools::promote_args<T>::type>::type
+ legendre_p_prime(int l, T x, const Policy& pol);
#endif
template <class T>
typename tools::promote_args<T>::type
@@ -1147,6 +1162,10 @@ namespace boost
\
template <class T>\
inline typename boost::math::tools::promote_args<T>::type \
+ legendre_p_prime(int l, T x){ return ::boost::math::legendre_p(l, x, Policy()); }\
+\
+ template <class T>\
+ inline typename boost::math::tools::promote_args<T>::type \
legendre_q(unsigned l, T x){ return ::boost::math::legendre_q(l, x, Policy()); }\
\
using ::boost::math::legendre_next;\
@@ -1593,5 +1612,3 @@ template <class OutputIterator, class T>\
#endif // BOOST_MATH_SPECIAL_MATH_FWD_HPP
-
-
diff --git a/boost/math/special_functions/next.hpp b/boost/math/special_functions/next.hpp
index 3921b70ce0..f23ddaffe3 100644
--- a/boost/math/special_functions/next.hpp
+++ b/boost/math/special_functions/next.hpp
@@ -27,9 +27,59 @@
namespace boost{ namespace math{
+ namespace concepts {
+
+ struct real_concept;
+ struct std_real_concept;
+
+ }
+
namespace detail{
template <class T>
+struct has_hidden_guard_digits;
+template <>
+struct has_hidden_guard_digits<float> : public mpl::false_ {};
+template <>
+struct has_hidden_guard_digits<double> : public mpl::false_ {};
+template <>
+struct has_hidden_guard_digits<long double> : public mpl::false_ {};
+#ifdef BOOST_HAS_FLOAT128
+template <>
+struct has_hidden_guard_digits<__float128> : public mpl::false_ {};
+#endif
+template <>
+struct has_hidden_guard_digits<boost::math::concepts::real_concept> : public mpl::false_ {};
+template <>
+struct has_hidden_guard_digits<boost::math::concepts::std_real_concept> : public mpl::false_ {};
+
+template <class T, bool b>
+struct has_hidden_guard_digits_10 : public mpl::false_ {};
+template <class T>
+struct has_hidden_guard_digits_10<T, true> : public mpl::bool_<(std::numeric_limits<T>::digits10 != std::numeric_limits<T>::max_digits10)> {};
+
+template <class T>
+struct has_hidden_guard_digits
+ : public has_hidden_guard_digits_10<T,
+ std::numeric_limits<T>::is_specialized
+ && (std::numeric_limits<T>::radix == 10) >
+{};
+
+template <class T>
+inline const T& normalize_value(const T& val, const mpl::false_&) { return val; }
+template <class T>
+inline T normalize_value(const T& val, const mpl::true_&)
+{
+ BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
+ BOOST_STATIC_ASSERT(std::numeric_limits<T>::radix != 2);
+
+ boost::intmax_t shift = std::numeric_limits<T>::digits - ilogb(val) - 1;
+ T result = scalbn(val, shift);
+ result = round(result);
+ return scalbn(result, -shift);
+}
+
+template <class T>
inline T get_smallest_value(mpl::true_ const&)
{
//
@@ -93,19 +143,33 @@ struct min_shift_initializer
template <class T>
const typename min_shift_initializer<T>::init min_shift_initializer<T>::initializer;
+template <class T>
+inline T calc_min_shifted(const mpl::true_&)
+{
+ BOOST_MATH_STD_USING
+ return ldexp(tools::min_value<T>(), tools::digits<T>() + 1);
+}
+template <class T>
+inline T calc_min_shifted(const mpl::false_&)
+{
+ BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
+ BOOST_STATIC_ASSERT(std::numeric_limits<T>::radix != 2);
+
+ return scalbn(tools::min_value<T>(), std::numeric_limits<T>::digits + 1);
+}
+
template <class T>
inline T get_min_shift_value()
{
- BOOST_MATH_STD_USING
- static const T val = ldexp(tools::min_value<T>(), tools::digits<T>() + 1);
+ static const T val = calc_min_shifted<T>(mpl::bool_<!std::numeric_limits<T>::is_specialized || std::numeric_limits<T>::radix == 2>());
min_shift_initializer<T>::force_instantiate();
return val;
}
template <class T, class Policy>
-T float_next_imp(const T& val, const Policy& pol)
+T float_next_imp(const T& val, const mpl::true_&, const Policy& pol)
{
BOOST_MATH_STD_USING
int expon;
@@ -145,6 +209,54 @@ T float_next_imp(const T& val, const Policy& pol)
diff = detail::get_smallest_value<T>();
return val + diff;
} // float_next_imp
+//
+// Special version for some base other than 2:
+//
+template <class T, class Policy>
+T float_next_imp(const T& val, const mpl::false_&, const Policy& pol)
+{
+ BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
+ BOOST_STATIC_ASSERT(std::numeric_limits<T>::radix != 2);
+
+ BOOST_MATH_STD_USING
+ boost::intmax_t expon;
+ static const char* function = "float_next<%1%>(%1%)";
+
+ int fpclass = (boost::math::fpclassify)(val);
+
+ if((fpclass == (int)FP_NAN) || (fpclass == (int)FP_INFINITE))
+ {
+ if(val < 0)
+ return -tools::max_value<T>();
+ return policies::raise_domain_error<T>(
+ function,
+ "Argument must be finite, but got %1%", val, pol);
+ }
+
+ if(val >= tools::max_value<T>())
+ return policies::raise_overflow_error<T>(function, 0, pol);
+
+ if(val == 0)
+ return detail::get_smallest_value<T>();
+
+ if((fpclass != (int)FP_SUBNORMAL) && (fpclass != (int)FP_ZERO) && (fabs(val) < detail::get_min_shift_value<T>()) && (val != -tools::min_value<T>()))
+ {
+ //
+ // Special case: if the value of the least significant bit is a denorm, and the result
+ // would not be a denorm, then shift the input, increment, and shift back.
+ // This avoids issues with the Intel SSE2 registers when the FTZ or DAZ flags are set.
+ //
+ return scalbn(float_next(T(scalbn(val, 2 * std::numeric_limits<T>::digits)), pol), -2 * std::numeric_limits<T>::digits);
+ }
+
+ expon = 1 + ilogb(val);
+ if(-1 == scalbn(val, -expon) * std::numeric_limits<T>::radix)
+ --expon; // reduce exponent when val is a power of base, and negative.
+ T diff = scalbn(T(1), expon - std::numeric_limits<T>::digits);
+ if(diff == 0)
+ diff = detail::get_smallest_value<T>();
+ return val + diff;
+} // float_next_imp
} // namespace detail
@@ -152,7 +264,7 @@ template <class T, class Policy>
inline typename tools::promote_args<T>::type float_next(const T& val, const Policy& pol)
{
typedef typename tools::promote_args<T>::type result_type;
- return detail::float_next_imp(static_cast<result_type>(val), pol);
+ return detail::float_next_imp(detail::normalize_value(static_cast<result_type>(val), typename detail::has_hidden_guard_digits<result_type>::type()), mpl::bool_<!std::numeric_limits<result_type>::is_specialized || (std::numeric_limits<result_type>::radix == 2)>(), pol);
}
#if 0 //def BOOST_MSVC
@@ -187,7 +299,7 @@ inline typename tools::promote_args<T>::type float_next(const T& val)
namespace detail{
template <class T, class Policy>
-T float_prior_imp(const T& val, const Policy& pol)
+T float_prior_imp(const T& val, const mpl::true_&, const Policy& pol)
{
BOOST_MATH_STD_USING
int expon;
@@ -221,13 +333,62 @@ T float_prior_imp(const T& val, const Policy& pol)
}
T remain = frexp(val, &expon);
- if(remain == 0.5)
+ if(remain == 0.5f)
--expon; // when val is a power of two we must reduce the exponent
T diff = ldexp(T(1), expon - tools::digits<T>());
if(diff == 0)
diff = detail::get_smallest_value<T>();
return val - diff;
} // float_prior_imp
+//
+// Special version for bases other than 2:
+//
+template <class T, class Policy>
+T float_prior_imp(const T& val, const mpl::false_&, const Policy& pol)
+{
+ BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
+ BOOST_STATIC_ASSERT(std::numeric_limits<T>::radix != 2);
+
+ BOOST_MATH_STD_USING
+ boost::intmax_t expon;
+ static const char* function = "float_prior<%1%>(%1%)";
+
+ int fpclass = (boost::math::fpclassify)(val);
+
+ if((fpclass == (int)FP_NAN) || (fpclass == (int)FP_INFINITE))
+ {
+ if(val > 0)
+ return tools::max_value<T>();
+ return policies::raise_domain_error<T>(
+ function,
+ "Argument must be finite, but got %1%", val, pol);
+ }
+
+ if(val <= -tools::max_value<T>())
+ return -policies::raise_overflow_error<T>(function, 0, pol);
+
+ if(val == 0)
+ return -detail::get_smallest_value<T>();
+
+ if((fpclass != (int)FP_SUBNORMAL) && (fpclass != (int)FP_ZERO) && (fabs(val) < detail::get_min_shift_value<T>()) && (val != tools::min_value<T>()))
+ {
+ //
+ // Special case: if the value of the least significant bit is a denorm, and the result
+ // would not be a denorm, then shift the input, increment, and shift back.
+ // This avoids issues with the Intel SSE2 registers when the FTZ or DAZ flags are set.
+ //
+ return scalbn(float_prior(T(scalbn(val, 2 * std::numeric_limits<T>::digits)), pol), -2 * std::numeric_limits<T>::digits);
+ }
+
+ expon = 1 + ilogb(val);
+ T remain = scalbn(val, -expon);
+ if(remain * std::numeric_limits<T>::radix == 1)
+ --expon; // when val is a power of two we must reduce the exponent
+ T diff = scalbn(T(1), expon - std::numeric_limits<T>::digits);
+ if(diff == 0)
+ diff = detail::get_smallest_value<T>();
+ return val - diff;
+} // float_prior_imp
} // namespace detail
@@ -235,7 +396,7 @@ template <class T, class Policy>
inline typename tools::promote_args<T>::type float_prior(const T& val, const Policy& pol)
{
typedef typename tools::promote_args<T>::type result_type;
- return detail::float_prior_imp(static_cast<result_type>(val), pol);
+ return detail::float_prior_imp(detail::normalize_value(static_cast<result_type>(val), typename detail::has_hidden_guard_digits<result_type>::type()), mpl::bool_<!std::numeric_limits<result_type>::is_specialized || (std::numeric_limits<result_type>::radix == 2)>(), pol);
}
#if 0 //def BOOST_MSVC
@@ -283,7 +444,7 @@ inline typename tools::promote_args<T, U>::type nextafter(const T& val, const U&
namespace detail{
template <class T, class Policy>
-T float_distance_imp(const T& a, const T& b, const Policy& pol)
+T float_distance_imp(const T& a, const T& b, const mpl::true_&, const Policy& pol)
{
BOOST_MATH_STD_USING
//
@@ -331,19 +492,23 @@ T float_distance_imp(const T& a, const T& b, const Policy& pol)
frexp(((boost::math::fpclassify)(a) == (int)FP_SUBNORMAL) ? tools::min_value<T>() : a, &expon);
T upper = ldexp(T(1), expon);
T result = T(0);
- expon = tools::digits<T>() - expon;
//
// If b is greater than upper, then we *must* split the calculation
// as the size of the ULP changes with each order of magnitude change:
//
if(b > upper)
{
- result = float_distance(upper, b);
+ int expon2;
+ frexp(b, &expon2);
+ T upper2 = ldexp(T(0.5), expon2);
+ result = float_distance(upper2, b);
+ result += (expon2 - expon - 1) * ldexp(T(1), tools::digits<T>() - 1);
}
//
// Use compensated double-double addition to avoid rounding
// errors in the subtraction:
//
+ expon = tools::digits<T>() - expon;
T mb, x, y, z;
if(((boost::math::fpclassify)(a) == (int)FP_SUBNORMAL) || (b - a < tools::min_value<T>()))
{
@@ -380,6 +545,113 @@ T float_distance_imp(const T& a, const T& b, const Policy& pol)
BOOST_ASSERT(result == floor(result));
return result;
} // float_distance_imp
+//
+// Special versions for bases other than 2:
+//
+template <class T, class Policy>
+T float_distance_imp(const T& a, const T& b, const mpl::false_&, const Policy& pol)
+{
+ BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
+ BOOST_STATIC_ASSERT(std::numeric_limits<T>::radix != 2);
+
+ BOOST_MATH_STD_USING
+ //
+ // Error handling:
+ //
+ static const char* function = "float_distance<%1%>(%1%, %1%)";
+ if(!(boost::math::isfinite)(a))
+ return policies::raise_domain_error<T>(
+ function,
+ "Argument a must be finite, but got %1%", a, pol);
+ if(!(boost::math::isfinite)(b))
+ return policies::raise_domain_error<T>(
+ function,
+ "Argument b must be finite, but got %1%", b, pol);
+ //
+ // Special cases:
+ //
+ if(a > b)
+ return -float_distance(b, a, pol);
+ if(a == b)
+ return T(0);
+ if(a == 0)
+ return 1 + fabs(float_distance(static_cast<T>((b < 0) ? T(-detail::get_smallest_value<T>()) : detail::get_smallest_value<T>()), b, pol));
+ if(b == 0)
+ return 1 + fabs(float_distance(static_cast<T>((a < 0) ? T(-detail::get_smallest_value<T>()) : detail::get_smallest_value<T>()), a, pol));
+ if(boost::math::sign(a) != boost::math::sign(b))
+ return 2 + fabs(float_distance(static_cast<T>((b < 0) ? T(-detail::get_smallest_value<T>()) : detail::get_smallest_value<T>()), b, pol))
+ + fabs(float_distance(static_cast<T>((a < 0) ? T(-detail::get_smallest_value<T>()) : detail::get_smallest_value<T>()), a, pol));
+ //
+ // By the time we get here, both a and b must have the same sign, we want
+ // b > a and both postive for the following logic:
+ //
+ if(a < 0)
+ return float_distance(static_cast<T>(-b), static_cast<T>(-a), pol);
+
+ BOOST_ASSERT(a >= 0);
+ BOOST_ASSERT(b >= a);
+
+ boost::intmax_t expon;
+ //
+ // Note that if a is a denorm then the usual formula fails
+ // because we actually have fewer than tools::digits<T>()
+ // significant bits in the representation:
+ //
+ expon = 1 + ilogb(((boost::math::fpclassify)(a) == (int)FP_SUBNORMAL) ? tools::min_value<T>() : a);
+ T upper = scalbn(T(1), expon);
+ T result = T(0);
+ //
+ // If b is greater than upper, then we *must* split the calculation
+ // as the size of the ULP changes with each order of magnitude change:
+ //
+ if(b > upper)
+ {
+ boost::intmax_t expon2 = 1 + ilogb(b);
+ T upper2 = scalbn(T(1), expon2 - 1);
+ result = float_distance(upper2, b);
+ result += (expon2 - expon - 1) * scalbn(T(1), std::numeric_limits<T>::digits - 1);
+ }
+ //
+ // Use compensated double-double addition to avoid rounding
+ // errors in the subtraction:
+ //
+ expon = std::numeric_limits<T>::digits - expon;
+ T mb, x, y, z;
+ if(((boost::math::fpclassify)(a) == (int)FP_SUBNORMAL) || (b - a < tools::min_value<T>()))
+ {
+ //
+ // Special case - either one end of the range is a denormal, or else the difference is.
+ // The regular code will fail if we're using the SSE2 registers on Intel and either
+ // the FTZ or DAZ flags are set.
+ //
+ T a2 = scalbn(a, std::numeric_limits<T>::digits);
+ T b2 = scalbn(b, std::numeric_limits<T>::digits);
+ mb = -(std::min)(T(scalbn(upper, std::numeric_limits<T>::digits)), b2);
+ x = a2 + mb;
+ z = x - a2;
+ y = (a2 - (x - z)) + (mb - z);
+
+ expon -= std::numeric_limits<T>::digits;
+ }
+ else
+ {
+ mb = -(std::min)(upper, b);
+ x = a + mb;
+ z = x - a;
+ y = (a - (x - z)) + (mb - z);
+ }
+ if(x < 0)
+ {
+ x = -x;
+ y = -y;
+ }
+ result += scalbn(x, expon) + scalbn(y, expon);
+ //
+ // Result must be an integer:
+ //
+ BOOST_ASSERT(result == floor(result));
+ return result;
+} // float_distance_imp
} // namespace detail
@@ -387,7 +659,7 @@ template <class T, class U, class Policy>
inline typename tools::promote_args<T, U>::type float_distance(const T& a, const U& b, const Policy& pol)
{
typedef typename tools::promote_args<T, U>::type result_type;
- return detail::float_distance_imp(static_cast<result_type>(a), static_cast<result_type>(b), pol);
+ return detail::float_distance_imp(detail::normalize_value(static_cast<result_type>(a), typename detail::has_hidden_guard_digits<result_type>::type()), detail::normalize_value(static_cast<result_type>(b), typename detail::has_hidden_guard_digits<result_type>::type()), mpl::bool_<!std::numeric_limits<result_type>::is_specialized || (std::numeric_limits<result_type>::radix == 2)>(), pol);
}
template <class T, class U>
@@ -399,7 +671,7 @@ typename tools::promote_args<T, U>::type float_distance(const T& a, const U& b)
namespace detail{
template <class T, class Policy>
-T float_advance_imp(T val, int distance, const Policy& pol)
+T float_advance_imp(T val, int distance, const mpl::true_&, const Policy& pol)
{
BOOST_MATH_STD_USING
//
@@ -478,6 +750,92 @@ T float_advance_imp(T val, int distance, const Policy& pol)
diff = distance * detail::get_smallest_value<T>();
return val += diff;
} // float_advance_imp
+//
+// Special version for bases other than 2:
+//
+template <class T, class Policy>
+T float_advance_imp(T val, int distance, const mpl::false_&, const Policy& pol)
+{
+ BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
+ BOOST_STATIC_ASSERT(std::numeric_limits<T>::radix != 2);
+
+ BOOST_MATH_STD_USING
+ //
+ // Error handling:
+ //
+ static const char* function = "float_advance<%1%>(%1%, int)";
+
+ int fpclass = (boost::math::fpclassify)(val);
+
+ if((fpclass == (int)FP_NAN) || (fpclass == (int)FP_INFINITE))
+ return policies::raise_domain_error<T>(
+ function,
+ "Argument val must be finite, but got %1%", val, pol);
+
+ if(val < 0)
+ return -float_advance(-val, -distance, pol);
+ if(distance == 0)
+ return val;
+ if(distance == 1)
+ return float_next(val, pol);
+ if(distance == -1)
+ return float_prior(val, pol);
+
+ if(fabs(val) < detail::get_min_shift_value<T>())
+ {
+ //
+ // Special case: if the value of the least significant bit is a denorm,
+ // implement in terms of float_next/float_prior.
+ // This avoids issues with the Intel SSE2 registers when the FTZ or DAZ flags are set.
+ //
+ if(distance > 0)
+ {
+ do{ val = float_next(val, pol); } while(--distance);
+ }
+ else
+ {
+ do{ val = float_prior(val, pol); } while(++distance);
+ }
+ return val;
+ }
+
+ boost::intmax_t expon = 1 + ilogb(val);
+ T limit = scalbn(T(1), distance < 0 ? expon - 1 : expon);
+ if(val <= tools::min_value<T>())
+ {
+ limit = sign(T(distance)) * tools::min_value<T>();
+ }
+ T limit_distance = float_distance(val, limit);
+ while(fabs(limit_distance) < abs(distance))
+ {
+ distance -= itrunc(limit_distance);
+ val = limit;
+ if(distance < 0)
+ {
+ limit /= std::numeric_limits<T>::radix;
+ expon--;
+ }
+ else
+ {
+ limit *= std::numeric_limits<T>::radix;
+ expon++;
+ }
+ limit_distance = float_distance(val, limit);
+ if(distance && (limit_distance == 0))
+ {
+ return policies::raise_evaluation_error<T>(function, "Internal logic failed while trying to increment floating point value %1%: most likely your FPU is in non-IEEE conforming mode.", val, pol);
+ }
+ }
+ /*expon = 1 + ilogb(val);
+ if((1 == scalbn(val, 1 + expon)) && (distance < 0))
+ --expon;*/
+ T diff = 0;
+ if(val != 0)
+ diff = distance * scalbn(T(1), expon - std::numeric_limits<T>::digits);
+ if(diff == 0)
+ diff = distance * detail::get_smallest_value<T>();
+ return val += diff;
+} // float_advance_imp
} // namespace detail
@@ -485,7 +843,7 @@ template <class T, class Policy>
inline typename tools::promote_args<T>::type float_advance(T val, int distance, const Policy& pol)
{
typedef typename tools::promote_args<T>::type result_type;
- return detail::float_advance_imp(static_cast<result_type>(val), distance, pol);
+ return detail::float_advance_imp(detail::normalize_value(static_cast<result_type>(val), typename detail::has_hidden_guard_digits<result_type>::type()), distance, mpl::bool_<!std::numeric_limits<result_type>::is_specialized || (std::numeric_limits<result_type>::radix == 2)>(), pol);
}
template <class T>
diff --git a/boost/math/special_functions/sign.hpp b/boost/math/special_functions/sign.hpp
index 3324c90a87..5cb21bac54 100644
--- a/boost/math/special_functions/sign.hpp
+++ b/boost/math/special_functions/sign.hpp
@@ -27,7 +27,7 @@ namespace detail {
template<class T>
inline int signbit_impl(T x, native_tag const&)
{
- return (std::signbit)(x);
+ return (std::signbit)(x) ? 1 : 0;
}
#endif
diff --git a/boost/math/special_functions/ulp.hpp b/boost/math/special_functions/ulp.hpp
index 3d78a1c7c2..bb0332a7e0 100644
--- a/boost/math/special_functions/ulp.hpp
+++ b/boost/math/special_functions/ulp.hpp
@@ -18,7 +18,7 @@
namespace boost{ namespace math{ namespace detail{
template <class T, class Policy>
-T ulp_imp(const T& val, const Policy& pol)
+T ulp_imp(const T& val, const mpl::true_&, const Policy& pol)
{
BOOST_MATH_STD_USING
int expon;
@@ -48,6 +48,40 @@ T ulp_imp(const T& val, const Policy& pol)
diff = detail::get_smallest_value<T>();
return diff;
}
+// non-binary version:
+template <class T, class Policy>
+T ulp_imp(const T& val, const mpl::false_&, const Policy& pol)
+{
+ BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
+ BOOST_STATIC_ASSERT(std::numeric_limits<T>::radix != 2);
+ BOOST_MATH_STD_USING
+ int expon;
+ static const char* function = "ulp<%1%>(%1%)";
+
+ int fpclass = (boost::math::fpclassify)(val);
+
+ if(fpclass == (int)FP_NAN)
+ {
+ return policies::raise_domain_error<T>(
+ function,
+ "Argument must be finite, but got %1%", val, pol);
+ }
+ else if((fpclass == (int)FP_INFINITE) || (fabs(val) >= tools::max_value<T>()))
+ {
+ return (val < 0 ? -1 : 1) * policies::raise_overflow_error<T>(function, 0, pol);
+ }
+ else if(fpclass == FP_ZERO)
+ return detail::get_smallest_value<T>();
+ //
+ // This code is almost the same as that for float_next, except for negative integers,
+ // where we preserve the relation ulp(x) == ulp(-x) as does Java:
+ //
+ expon = 1 + ilogb(fabs(val));
+ T diff = scalbn(T(1), expon - std::numeric_limits<T>::digits);
+ if(diff == 0)
+ diff = detail::get_smallest_value<T>();
+ return diff;
+}
}
@@ -55,7 +89,7 @@ template <class T, class Policy>
inline typename tools::promote_args<T>::type ulp(const T& val, const Policy& pol)
{
typedef typename tools::promote_args<T>::type result_type;
- return detail::ulp_imp(static_cast<result_type>(val), pol);
+ return detail::ulp_imp(static_cast<result_type>(val), mpl::bool_<!std::numeric_limits<result_type>::is_specialized || (std::numeric_limits<result_type>::radix == 2)>(), pol);
}
template <class T>
diff --git a/boost/math/tools/polynomial.hpp b/boost/math/tools/polynomial.hpp
index 464c334d10..56c4e6895e 100644
--- a/boost/math/tools/polynomial.hpp
+++ b/boost/math/tools/polynomial.hpp
@@ -15,7 +15,6 @@
#include <boost/assert.hpp>
#include <boost/config.hpp>
-#include <boost/config/suffix.hpp>
#include <boost/function.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/math/tools/rational.hpp>
@@ -713,6 +712,11 @@ inline std::basic_ostream<charT, traits>& operator << (std::basic_ostream<charT,
} // namespace math
} // namespace boost
+//
+// Polynomial specific overload of gcd algorithm:
+//
+#include <boost/math/tools/polynomial_gcd.hpp>
+
#endif // BOOST_MATH_TOOLS_POLYNOMIAL_HPP
diff --git a/boost/math/tools/polynomial_gcd.hpp b/boost/math/tools/polynomial_gcd.hpp
new file mode 100644
index 0000000000..fdbafda6ca
--- /dev/null
+++ b/boost/math/tools/polynomial_gcd.hpp
@@ -0,0 +1,209 @@
+// (C) Copyright Jeremy William Murphy 2016.
+
+// 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_MATH_TOOLS_POLYNOMIAL_GCD_HPP
+#define BOOST_MATH_TOOLS_POLYNOMIAL_GCD_HPP
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+
+#include <boost/math/tools/polynomial.hpp>
+#include <boost/math/common_factor_rt.hpp>
+#include <boost/type_traits/is_pod.hpp>
+
+
+namespace boost{
+
+ namespace integer {
+
+ namespace gcd_detail {
+
+ template <class T>
+ struct gcd_traits;
+
+ template <class T>
+ struct gcd_traits<boost::math::tools::polynomial<T> >
+ {
+ inline static const boost::math::tools::polynomial<T>& abs(const boost::math::tools::polynomial<T>& val) { return val; }
+
+ static const method_type method = method_euclid;
+ };
+
+ }
+}
+
+
+
+namespace math{ namespace tools{
+
+/* From Knuth, 4.6.1:
+*
+* We may write any nonzero polynomial u(x) from R[x] where R is a UFD as
+*
+* u(x) = cont(u) · pp(u(x))
+*
+* where cont(u), the content of u, is an element of S, and pp(u(x)), the primitive
+* part of u(x), is a primitive polynomial over S.
+* When u(x) = 0, it is convenient to define cont(u) = pp(u(x)) = O.
+*/
+
+template <class T>
+T content(polynomial<T> const &x)
+{
+ return x ? gcd_range(x.data().begin(), x.data().end()).first : T(0);
+}
+
+// Knuth, 4.6.1
+template <class T>
+polynomial<T> primitive_part(polynomial<T> const &x, T const &cont)
+{
+ return x ? x / cont : polynomial<T>();
+}
+
+
+template <class T>
+polynomial<T> primitive_part(polynomial<T> const &x)
+{
+ return primitive_part(x, content(x));
+}
+
+
+// Trivial but useful convenience function referred to simply as l() in Knuth.
+template <class T>
+T leading_coefficient(polynomial<T> const &x)
+{
+ return x ? x.data().back() : T(0);
+}
+
+
+namespace detail
+{
+ /* Reduce u and v to their primitive parts and return the gcd of their
+ * contents. Used in a couple of gcd algorithms.
+ */
+ template <class T>
+ T reduce_to_primitive(polynomial<T> &u, polynomial<T> &v)
+ {
+ using boost::math::gcd;
+ T const u_cont = content(u), v_cont = content(v);
+ u /= u_cont;
+ v /= v_cont;
+ return gcd(u_cont, v_cont);
+ }
+}
+
+
+/**
+* Knuth, The Art of Computer Programming: Volume 2, Third edition, 1998
+* Algorithm 4.6.1C: Greatest common divisor over a unique factorization domain.
+*
+* The subresultant algorithm by George E. Collins [JACM 14 (1967), 128-142],
+* later improved by W. S. Brown and J. F. Traub [JACM 18 (1971), 505-514].
+*
+* Although step C3 keeps the coefficients to a "reasonable" size, they are
+* still potentially several binary orders of magnitude larger than the inputs.
+* Thus, this algorithm should only be used where T is a multi-precision type.
+*
+* @tparam T Polynomial coefficient type.
+* @param u First polynomial.
+* @param v Second polynomial.
+* @return Greatest common divisor of polynomials u and v.
+*/
+template <class T>
+typename enable_if_c< std::numeric_limits<T>::is_integer, polynomial<T> >::type
+subresultant_gcd(polynomial<T> u, polynomial<T> v)
+{
+ using std::swap;
+ BOOST_ASSERT(u || v);
+
+ if (!u)
+ return v;
+ if (!v)
+ return u;
+
+ typedef typename polynomial<T>::size_type N;
+
+ if (u.degree() < v.degree())
+ swap(u, v);
+
+ T const d = detail::reduce_to_primitive(u, v);
+ T g = 1, h = 1;
+ polynomial<T> r;
+ while (true)
+ {
+ BOOST_ASSERT(u.degree() >= v.degree());
+ // Pseudo-division.
+ r = u % v;
+ if (!r)
+ return d * primitive_part(v); // Attach the content.
+ if (r.degree() == 0)
+ return d * polynomial<T>(T(1)); // The content is the result.
+ N const delta = u.degree() - v.degree();
+ // Adjust remainder.
+ u = v;
+ v = r / (g * detail::integer_power(h, delta));
+ g = leading_coefficient(u);
+ T const tmp = detail::integer_power(g, delta);
+ if (delta <= N(1))
+ h = tmp * detail::integer_power(h, N(1) - delta);
+ else
+ h = tmp / detail::integer_power(h, delta - N(1));
+ }
+}
+
+
+/**
+ * @brief GCD for polynomials with unbounded multi-precision integral coefficients.
+ *
+ * The multi-precision constraint is enforced via numeric_limits.
+ *
+ * Note that intermediate terms in the evaluation can grow arbitrarily large, hence the need for
+ * unbounded integers, otherwise numeric loverflow would break the algorithm.
+ *
+ * @tparam T A multi-precision integral type.
+ */
+template <typename T>
+typename enable_if_c<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_bounded, polynomial<T> >::type
+gcd(polynomial<T> const &u, polynomial<T> const &v)
+{
+ return subresultant_gcd(u, v);
+}
+// GCD over bounded integers is not currently allowed:
+template <typename T>
+typename enable_if_c<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_bounded, polynomial<T> >::type
+gcd(polynomial<T> const &u, polynomial<T> const &v)
+{
+ BOOST_STATIC_ASSERT_MSG(sizeof(v) == 0, "GCD on polynomials of bounded integers is disallowed due to the excessive growth in the size of intermediate terms.");
+ return subresultant_gcd(u, v);
+}
+// GCD over polynomials of floats can go via the Euclid algorithm:
+template <typename T>
+typename enable_if_c<!std::numeric_limits<T>::is_integer && (std::numeric_limits<T>::min_exponent != std::numeric_limits<T>::max_exponent) && !std::numeric_limits<T>::is_exact, polynomial<T> >::type
+gcd(polynomial<T> const &u, polynomial<T> const &v)
+{
+ return boost::integer::gcd_detail::Euclid_gcd(u, v);
+}
+
+}
+//
+// Using declaration so we overload the default implementation in this namespace:
+//
+using boost::math::tools::gcd;
+
+}
+
+namespace integer
+{
+ //
+ // Using declaration so we overload the default implementation in this namespace:
+ //
+ using boost::math::tools::gcd;
+}
+
+} // namespace boost::math::tools
+
+#endif
diff --git a/boost/math_fwd.hpp b/boost/math_fwd.hpp
index 9c9147ae12..41b4669b3d 100644
--- a/boost/math_fwd.hpp
+++ b/boost/math_fwd.hpp
@@ -44,52 +44,6 @@ template < >
template < >
class octonion< long double >;
-// Also has many function templates (including operators)
-
-
-// From <boost/math/special_functions/acosh.hpp> ---------------------------//
-
-// Only has function template
-
-
-// From <boost/math/special_functions/asinh.hpp> ---------------------------//
-
-// Only has function template
-
-
-// From <boost/math/special_functions/atanh.hpp> ---------------------------//
-
-// Only has function template
-
-
-// From <boost/math/special_functions/sinc.hpp> ----------------------------//
-
-// Only has function templates
-
-
-// From <boost/math/special_functions/sinhc.hpp> ---------------------------//
-
-// Only has function templates
-
-
-// From <boost/math/common_factor.hpp> -------------------------------------//
-
-// Only #includes other headers
-
-
-// From <boost/math/common_factor_ct.hpp> ----------------------------------//
-
-#ifdef BOOST_NO_INTEGRAL_INT64_T
- typedef unsigned long static_gcd_type;
-#else
- typedef boost::uintmax_t static_gcd_type;
-#endif
-
-template < static_gcd_type Value1, static_gcd_type Value2 >
- struct static_gcd;
-template < static_gcd_type Value1, static_gcd_type Value2 >
- struct static_lcm;
-
} // namespace math
} // namespace boost
diff --git a/boost/metaparse/config.hpp b/boost/metaparse/config.hpp
index a9a42dbb60..2e8e6a2931 100644
--- a/boost/metaparse/config.hpp
+++ b/boost/metaparse/config.hpp
@@ -24,17 +24,40 @@
#endif
/*
- * Metaparse config
+ * C++ standard to use
*/
-#if \
- !defined BOOST_NO_CXX11_VARIADIC_TEMPLATES \
- && !defined BOOST_NO_VARIADIC_TEMPLATES \
- && !defined BOOST_METAPARSE_VARIADIC_STRING
+// Allow overriding this
+#ifndef BOOST_METAPARSE_STD
-# define BOOST_METAPARSE_VARIADIC_STRING
+// special-case MSCV >= 1900 as its constexpr support is good enough for
+// Metaparse
+# if \
+ !defined BOOST_NO_CXX11_VARIADIC_TEMPLATES \
+ && !defined BOOST_NO_VARIADIC_TEMPLATES \
+ && ( \
+ (!defined BOOST_NO_CONSTEXPR && !defined BOOST_NO_CXX11_CONSTEXPR) \
+ || (defined _MSC_VER && _MSC_VER >= 1900) \
+ ) \
+ && (!defined BOOST_GCC || BOOST_GCC >= 40700)
+
+# define BOOST_METAPARSE_STD 2011
+
+# else
+
+# define BOOST_METAPARSE_STD 1998
+
+# endif
#endif
+/*
+ * Metaparse config
+ */
+
+#if BOOST_METAPARSE_STD >= 2011
+# define BOOST_METAPARSE_VARIADIC_STRING
+#endif
+
#endif
diff --git a/boost/metaparse/v1/cpp11/fwd/string.hpp b/boost/metaparse/v1/cpp11/fwd/string.hpp
new file mode 100644
index 0000000000..562ade400d
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/fwd/string.hpp
@@ -0,0 +1,22 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_FWD_STRING_HPP
+#define BOOST_METAPARSE_V1_CPP11_FWD_STRING_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <char... Cs>
+ struct string;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp11/impl/at_c.hpp b/boost/metaparse/v1/cpp11/impl/at_c.hpp
new file mode 100644
index 0000000000..17332af1f6
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/impl/at_c.hpp
@@ -0,0 +1,35 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_IMPL_AT_C_HPP
+#define BOOST_METAPARSE_V1_CPP11_IMPL_AT_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
+
+#include <boost/metaparse/v1/cpp11/fwd/string.hpp>
+
+#include <boost/mpl/char.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class S, int N>
+ struct at_c;
+
+ template <char C, char... Cs, int N>
+ struct at_c<string<C, Cs...>, N> : at_c<string<Cs...>, N - 1> {};
+
+ template <char C, char... Cs>
+ struct at_c<string<C, Cs...>, 0> : boost::mpl::char_<C> {};
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp11/impl/concat.hpp b/boost/metaparse/v1/cpp11/impl/concat.hpp
new file mode 100644
index 0000000000..438a7766eb
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/impl/concat.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_IMPL_CONCAT_HPP
+#define BOOST_METAPARSE_V1_CPP11_IMPL_CONCAT_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
+
+#include <boost/metaparse/v1/cpp11/fwd/string.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class A, class B>
+ struct concat;
+
+ template <char... As, char... Bs>
+ struct concat<string<As...>, string<Bs...>> : string<As..., Bs...> {};
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp11/impl/empty_string.hpp b/boost/metaparse/v1/cpp11/impl/empty_string.hpp
new file mode 100644
index 0000000000..93b87e4184
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/impl/empty_string.hpp
@@ -0,0 +1,33 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_IMPL_EMPTY_STRING_HPP
+#define BOOST_METAPARSE_V1_CPP11_IMPL_EMPTY_STRING_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class Ignore = int>
+ struct empty_string
+ {
+ typedef empty_string type;
+
+ static constexpr char value[1] = {0};
+ };
+
+ template <class Ignore>
+ constexpr char empty_string<Ignore>::value[1];
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/pop_back.hpp b/boost/metaparse/v1/cpp11/impl/pop_back.hpp
index 7c3d9b30b2..224ee00b95 100644
--- a/boost/metaparse/v1/impl/pop_back.hpp
+++ b/boost/metaparse/v1/cpp11/impl/pop_back.hpp
@@ -1,16 +1,14 @@
-#ifndef BOOST_METAPARSE_V1_IMPL_POP_BACK_HPP
-#define BOOST_METAPARSE_V1_IMPL_POP_BACK_HPP
+#ifndef BOOST_METAPARSE_V1_CPP11_IMPL_POP_BACK_HPP
+#define BOOST_METAPARSE_V1_CPP11_IMPL_POP_BACK_HPP
// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
-#include <boost/metaparse/config.hpp>
-#include <boost/metaparse/v1/fwd/string.hpp>
-#include <boost/metaparse/v1/impl/push_front_c.hpp>
-#include <boost/metaparse/v1/impl/size.hpp>
-#include <boost/metaparse/v1/impl/update_c.hpp>
+#include <boost/metaparse/v1/cpp11/fwd/string.hpp>
+#include <boost/metaparse/v1/cpp11/impl/push_front_c.hpp>
+#include <boost/metaparse/v1/cpp11/impl/size.hpp>
#include <boost/mpl/clear.hpp>
@@ -25,7 +23,6 @@ namespace boost
template <class S>
struct pop_back;
-#ifdef BOOST_METAPARSE_VARIADIC_STRING
template <char C>
struct pop_back<string<C>> : boost::mpl::clear<string<C>> {};
@@ -33,16 +30,6 @@ namespace boost
struct pop_back<string<C, Cs...>> :
push_front_c<typename pop_back<string<Cs...>>::type, C>
{};
-#else
- template <class S>
- struct pop_back :
- update_c<
- typename S::type,
- size<typename S::type>::type::value - 1,
- BOOST_NO_CHAR
- >
- {};
-#endif
}
}
}
diff --git a/boost/metaparse/v1/cpp11/impl/pop_front.hpp b/boost/metaparse/v1/cpp11/impl/pop_front.hpp
new file mode 100644
index 0000000000..1d0dd74534
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/impl/pop_front.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_IMPL_POP_FRONT_HPP
+#define BOOST_METAPARSE_V1_CPP11_IMPL_POP_FRONT_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
+
+#include <boost/metaparse/v1/cpp11/fwd/string.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class S>
+ struct pop_front;
+
+ template <char C, char... Cs>
+ struct pop_front<string<C, Cs...>> : string<Cs...> {};
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp11/impl/push_back_c.hpp b/boost/metaparse/v1/cpp11/impl/push_back_c.hpp
new file mode 100644
index 0000000000..c1e6d86bc7
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/impl/push_back_c.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_IMPL_PUSH_BACK_C_HPP
+#define BOOST_METAPARSE_V1_CPP11_IMPL_PUSH_BACK_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
+
+#include <boost/metaparse/v1/cpp11/fwd/string.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class S, char C>
+ struct push_back_c;
+
+ template <char... Cs, char C>
+ struct push_back_c<string<Cs...>, C> : string<Cs..., C> {};
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp11/impl/push_front_c.hpp b/boost/metaparse/v1/cpp11/impl/push_front_c.hpp
new file mode 100644
index 0000000000..d450cffe70
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/impl/push_front_c.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_IMPL_PUSH_FRONT_C_HPP
+#define BOOST_METAPARSE_V1_CPP11_IMPL_PUSH_FRONT_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
+
+#include <boost/metaparse/v1/cpp11/fwd/string.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class S, char C>
+ struct push_front_c;
+
+ template <char... Cs, char C>
+ struct push_front_c<string<Cs...>, C> : string<C, Cs...> {};
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/remove_trailing_no_chars.hpp b/boost/metaparse/v1/cpp11/impl/remove_trailing_no_chars.hpp
index 7d561d2709..cdea6e4b7f 100644
--- a/boost/metaparse/v1/impl/remove_trailing_no_chars.hpp
+++ b/boost/metaparse/v1/cpp11/impl/remove_trailing_no_chars.hpp
@@ -1,14 +1,14 @@
-#ifndef BOOST_METAPARSE_V1_IMPL_REMOVE_TRAILING_NO_CHARS_HPP
-#define BOOST_METAPARSE_V1_IMPL_REMOVE_TRAILING_NO_CHARS_HPP
+#ifndef BOOST_METAPARSE_V1_CPP11_IMPL_REMOVE_TRAILING_NO_CHARS_HPP
+#define BOOST_METAPARSE_V1_CPP11_IMPL_REMOVE_TRAILING_NO_CHARS_HPP
// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
-#include <boost/metaparse/config.hpp>
-#include <boost/metaparse/v1/string.hpp>
-#include <boost/metaparse/v1/impl/push_front_c.hpp>
+#include <boost/metaparse/v1/cpp11/string.hpp>
+#include <boost/metaparse/v1/impl/no_char.hpp>
+#include <boost/metaparse/v1/cpp11/impl/push_front_c.hpp>
namespace boost
{
@@ -21,7 +21,6 @@ namespace boost
template <class S>
struct remove_trailing_no_chars : S {};
-#ifdef BOOST_METAPARSE_VARIADIC_STRING
// this code assumes that BOOST_NO_CHARs are at the end of the string
template <char... Cs>
struct remove_trailing_no_chars<string<BOOST_NO_CHAR, Cs...>> :
@@ -47,7 +46,6 @@ namespace boost
template <>
struct remove_trailing_no_chars<string<>> : string<> {};
#endif
-#endif
}
}
}
diff --git a/boost/metaparse/v1/cpp11/impl/size.hpp b/boost/metaparse/v1/cpp11/impl/size.hpp
new file mode 100644
index 0000000000..a1ffa1b2db
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/impl/size.hpp
@@ -0,0 +1,34 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_IMPL_SIZE_HPP
+#define BOOST_METAPARSE_V1_CPP11_IMPL_SIZE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
+
+#include <boost/metaparse/v1/cpp11/fwd/string.hpp>
+
+#include <boost/mpl/int.hpp>
+
+#include <type_traits>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class S>
+ struct size;
+
+ template <char... Cs>
+ struct size<string<Cs...>> : boost::mpl::int_<sizeof...(Cs)> {};
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/string.hpp b/boost/metaparse/v1/cpp11/impl/string.hpp
index d3843cfb34..0d31a55a4d 100644
--- a/boost/metaparse/v1/impl/string.hpp
+++ b/boost/metaparse/v1/cpp11/impl/string.hpp
@@ -1,11 +1,11 @@
-#ifndef BOOST_METAPARSE_V1_IMPL__HPP
-#define BOOST_METAPARSE_V1_IMPL__HPP
+#ifndef BOOST_METAPARSE_V1_CPP11_IMPL_STRING_HPP
+#define BOOST_METAPARSE_V1_CPP11_IMPL_STRING_HPP
// This is an automatically generated header file.
// Generated with the tools/string_headers.py utility of
// Boost.Metaparse
-#include <boost/metaparse/v1/impl/concat.hpp>
+#include <boost/metaparse/v1/cpp11/impl/concat.hpp>
#include <boost/preprocessor/cat.hpp>
namespace boost
diff --git a/boost/metaparse/v1/impl/string_at.hpp b/boost/metaparse/v1/cpp11/impl/string_at.hpp
index a465d302bf..6540d56f65 100644
--- a/boost/metaparse/v1/impl/string_at.hpp
+++ b/boost/metaparse/v1/cpp11/impl/string_at.hpp
@@ -1,15 +1,15 @@
-#ifndef BOOST_METAPARSE_V1_IMPL_STRING_AT_HPP
-#define BOOST_METAPARSE_V1_IMPL_STRING_AT_HPP
+#ifndef BOOST_METAPARSE_V1_CPP11_IMPL_STRING_AT_HPP
+#define BOOST_METAPARSE_V1_CPP11_IMPL_STRING_AT_HPP
// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
-#include <boost/metaparse/config.hpp>
-#include <boost/static_assert.hpp>
#include <boost/metaparse/v1/impl/no_char.hpp>
+#include <boost/metaparse/limit_string_size.hpp>
+
namespace boost
{
namespace metaparse
@@ -19,11 +19,11 @@ namespace boost
namespace impl
{
template <int MaxLen, int Len, class T>
- BOOST_CONSTEXPR int string_at(const T (&s)[Len], int n)
+ constexpr int string_at(const T (&s)[Len], int n)
{
// "MaxLen + 1" adds the \0 character of the string literal to the
// limit
- BOOST_STATIC_ASSERT((Len <= MaxLen + 1));
+ static_assert(Len <= MaxLen + 1, "String literal is too long.");
return n >= Len - 1 ? BOOST_NO_CHAR : s[n];
}
}
diff --git a/boost/metaparse/v1/cpp11/string.hpp b/boost/metaparse/v1/cpp11/string.hpp
new file mode 100644
index 0000000000..e109b41d98
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/string.hpp
@@ -0,0 +1,213 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_STRING_HPP
+#define BOOST_METAPARSE_V1_CPP11_STRING_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
+
+#include <boost/metaparse/v1/cpp11/fwd/string.hpp>
+#include <boost/metaparse/v1/string_tag.hpp>
+#include <boost/metaparse/v1/impl/string_iterator.hpp>
+#include <boost/metaparse/v1/cpp11/impl/empty_string.hpp>
+#include <boost/metaparse/v1/cpp11/impl/size.hpp>
+#include <boost/metaparse/v1/cpp11/impl/pop_front.hpp>
+#include <boost/metaparse/v1/cpp11/impl/push_front_c.hpp>
+#include <boost/metaparse/v1/cpp11/impl/push_back_c.hpp>
+#include <boost/metaparse/v1/cpp11/impl/pop_back.hpp>
+#include <boost/metaparse/v1/cpp11/impl/string_at.hpp>
+
+#include <type_traits>
+
+/*
+ * The string type
+ */
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <char... Cs>
+ struct string
+ {
+ typedef string type;
+ typedef string_tag tag;
+ };
+ }
+ }
+}
+
+/*
+ * Boost.MPL overloads
+ */
+
+namespace boost
+{
+ namespace mpl
+ {
+ // push_back
+ template <class S>
+ struct push_back_impl;
+
+ template <>
+ struct push_back_impl<boost::metaparse::v1::string_tag>
+ {
+ typedef push_back_impl type;
+
+ template <class S, class C>
+ struct apply :
+ boost::metaparse::v1::impl::push_back_c<
+ typename S::type,
+ C::type::value
+ >
+ {};
+ };
+
+ // pop_back
+ template <class S>
+ struct pop_back_impl;
+
+ template <>
+ struct pop_back_impl<boost::metaparse::v1::string_tag>
+ {
+ typedef pop_back_impl type;
+
+ template <class S>
+ struct apply : boost::metaparse::v1::impl::pop_back<S> {};
+ };
+
+ // push_front
+ template <class S>
+ struct push_front_impl;
+
+ template <>
+ struct push_front_impl<boost::metaparse::v1::string_tag>
+ {
+ typedef push_front_impl type;
+
+ template <class S, class C>
+ struct apply :
+ boost::metaparse::v1::impl::push_front_c<
+ typename S::type,
+ C::type::value
+ >
+ {};
+ };
+
+ // pop_front
+ template <class S>
+ struct pop_front_impl;
+
+ template <>
+ struct pop_front_impl<boost::metaparse::v1::string_tag>
+ {
+ typedef pop_front_impl type;
+
+ template <class S>
+ struct apply : boost::metaparse::v1::impl::pop_front<S> {};
+ };
+
+ // clear
+ template <class S>
+ struct clear_impl;
+
+ template <>
+ struct clear_impl<boost::metaparse::v1::string_tag>
+ {
+ typedef clear_impl type;
+
+ template <class S>
+ struct apply : boost::metaparse::v1::string<> {};
+ };
+
+ // begin
+ template <class S>
+ struct begin_impl;
+
+ template <>
+ struct begin_impl<boost::metaparse::v1::string_tag>
+ {
+ typedef begin_impl type;
+
+ template <class S>
+ struct apply :
+ boost::metaparse::v1::impl::string_iterator<typename S::type, 0>
+ {};
+ };
+
+ // end
+ template <class S>
+ struct end_impl;
+
+ template <>
+ struct end_impl<boost::metaparse::v1::string_tag>
+ {
+ typedef end_impl type;
+
+ template <class S>
+ struct apply :
+ boost::metaparse::v1::impl::string_iterator<
+ typename S::type,
+ boost::metaparse::v1::impl::size<typename S::type>::type::value
+ >
+ {};
+ };
+
+ // equal_to
+ template <class A, class B>
+ struct equal_to_impl;
+
+ template <>
+ struct equal_to_impl<
+ boost::metaparse::v1::string_tag,
+ boost::metaparse::v1::string_tag
+ >
+ {
+ typedef equal_to_impl type;
+
+ template <class A, class B>
+ struct apply : std::is_same<typename A::type, typename B::type> {};
+ };
+
+ template <class T>
+ struct equal_to_impl<boost::metaparse::v1::string_tag, T>
+ {
+ typedef equal_to_impl type;
+
+ template <class, class>
+ struct apply : false_ {};
+ };
+
+ template <class T>
+ struct equal_to_impl<T, boost::metaparse::v1::string_tag> :
+ equal_to_impl<boost::metaparse::v1::string_tag, T>
+ {};
+
+ // c_str
+ template <class S>
+ struct c_str;
+
+ template <char... Cs>
+ struct c_str<boost::metaparse::v1::string<Cs...>>
+ {
+ typedef c_str type;
+ static constexpr char value[sizeof...(Cs) + 1] = {Cs..., 0};
+ };
+
+ template <>
+ struct c_str<boost::metaparse::v1::string<>> :
+ boost::metaparse::v1::impl::empty_string<>
+ {};
+
+ template <char... Cs>
+ constexpr char c_str<boost::metaparse::v1::string<Cs...>>::value[];
+ }
+}
+
+#include <boost/metaparse/v1/cpp11/impl/remove_trailing_no_chars.hpp>
+#include <boost/metaparse/v1/cpp11/impl/string.hpp>
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp98/fwd/string.hpp b/boost/metaparse/v1/cpp98/fwd/string.hpp
new file mode 100644
index 0000000000..69d80adca5
--- /dev/null
+++ b/boost/metaparse/v1/cpp98/fwd/string.hpp
@@ -0,0 +1,33 @@
+#ifndef BOOST_METAPARSE_V1_CPP98_FWD_STRING_HPP
+#define BOOST_METAPARSE_V1_CPP98_FWD_STRING_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
+
+#include <boost/metaparse/limit_string_size.hpp>
+#include <boost/metaparse/v1/impl/no_char.hpp>
+
+#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <
+ BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
+ BOOST_METAPARSE_LIMIT_STRING_SIZE,
+ int C,
+ BOOST_NO_CHAR
+ )
+ >
+ struct string;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp98/impl/at_c.hpp b/boost/metaparse/v1/cpp98/impl/at_c.hpp
new file mode 100644
index 0000000000..469b3149e9
--- /dev/null
+++ b/boost/metaparse/v1/cpp98/impl/at_c.hpp
@@ -0,0 +1,58 @@
+#ifndef BOOST_METAPARSE_V1_CPP98_IMPL_AT_C_HPP
+#define BOOST_METAPARSE_V1_CPP98_IMPL_AT_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
+
+#include <boost/metaparse/config.hpp>
+#include <boost/metaparse/v1/cpp98/fwd/string.hpp>
+
+#include <boost/mpl/char.hpp>
+
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class S, int N>
+ struct at_c;
+
+ #ifdef BOOST_METAPARSE_STRING_CASE
+ # error BOOST_METAPARSE_STRING_CASE is already defined
+ #endif
+ #define BOOST_METAPARSE_STRING_CASE(z, n, unused) \
+ template < \
+ BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int C) \
+ > \
+ struct \
+ at_c< \
+ string< \
+ BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, C) \
+ >, \
+ n \
+ > : \
+ boost::mpl::char_<BOOST_PP_CAT(C, n)> \
+ {};
+
+ BOOST_PP_REPEAT(
+ BOOST_METAPARSE_LIMIT_STRING_SIZE,
+ BOOST_METAPARSE_STRING_CASE,
+ ~
+ )
+
+ #undef BOOST_METAPARSE_STRING_CASE
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp98/impl/empty_string.hpp b/boost/metaparse/v1/cpp98/impl/empty_string.hpp
new file mode 100644
index 0000000000..362fbd3cc5
--- /dev/null
+++ b/boost/metaparse/v1/cpp98/impl/empty_string.hpp
@@ -0,0 +1,33 @@
+#ifndef BOOST_METAPARSE_V1_CPP98_IMPL_EMPTY_STRING_HPP
+#define BOOST_METAPARSE_V1_CPP98_IMPL_EMPTY_STRING_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class Ignore = int>
+ struct empty_string
+ {
+ typedef empty_string type;
+
+ static const char value[1];
+ };
+
+ template <class Ignore>
+ const char empty_string<Ignore>::value[1] = {0};
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp98/impl/pop_back.hpp b/boost/metaparse/v1/cpp98/impl/pop_back.hpp
new file mode 100644
index 0000000000..e5273740b0
--- /dev/null
+++ b/boost/metaparse/v1/cpp98/impl/pop_back.hpp
@@ -0,0 +1,39 @@
+#ifndef BOOST_METAPARSE_V1_CPP98_IMPL_POP_BACK_HPP
+#define BOOST_METAPARSE_V1_CPP98_IMPL_POP_BACK_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
+
+#include <boost/metaparse/v1/cpp98/fwd/string.hpp>
+#include <boost/metaparse/v1/cpp98/impl/push_front_c.hpp>
+#include <boost/metaparse/v1/cpp98/impl/size.hpp>
+#include <boost/metaparse/v1/cpp98/impl/update_c.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class S>
+ struct pop_back;
+
+ template <class S>
+ struct pop_back :
+ update_c<
+ typename S::type,
+ size<typename S::type>::type::value - 1,
+ BOOST_NO_CHAR
+ >
+ {};
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/pop_front.hpp b/boost/metaparse/v1/cpp98/impl/pop_front.hpp
index ac02d35aa1..6302f0aced 100644
--- a/boost/metaparse/v1/impl/pop_front.hpp
+++ b/boost/metaparse/v1/cpp98/impl/pop_front.hpp
@@ -1,13 +1,12 @@
-#ifndef BOOST_METAPARSE_V1_IMPL_POP_FRONT_HPP
-#define BOOST_METAPARSE_V1_IMPL_POP_FRONT_HPP
+#ifndef BOOST_METAPARSE_V1_CPP98_IMPL_POP_FRONT_HPP
+#define BOOST_METAPARSE_V1_CPP98_IMPL_POP_FRONT_HPP
// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
-#include <boost/metaparse/config.hpp>
-#include <boost/metaparse/v1/fwd/string.hpp>
+#include <boost/metaparse/v1/cpp98/fwd/string.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
@@ -23,10 +22,6 @@ namespace boost
template <class S>
struct pop_front;
-#ifdef BOOST_METAPARSE_VARIADIC_STRING
- template <char C, char... Cs>
- struct pop_front<string<C, Cs...>> : string<Cs...> {};
-#else
#ifdef BOOST_METAPARSE_POP_FRONT
# error BOOST_METAPARSE_POP_FRONT already defined
#endif
@@ -52,7 +47,6 @@ namespace boost
{};
#undef BOOST_METAPARSE_POP_FRONT
-#endif
}
}
}
diff --git a/boost/metaparse/v1/impl/push_back_c.hpp b/boost/metaparse/v1/cpp98/impl/push_back_c.hpp
index 453043d97c..69f9eef02c 100644
--- a/boost/metaparse/v1/impl/push_back_c.hpp
+++ b/boost/metaparse/v1/cpp98/impl/push_back_c.hpp
@@ -1,15 +1,14 @@
-#ifndef BOOST_METAPARSE_V1_PUSH_BACK_C_HPP
-#define BOOST_METAPARSE_V1_PUSH_BACK_C_HPP
+#ifndef BOOST_METAPARSE_V1_CPP98_IMPL_PUSH_BACK_C_HPP
+#define BOOST_METAPARSE_V1_CPP98_IMPL_PUSH_BACK_C_HPP
// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
-#include <boost/metaparse/config.hpp>
-#include <boost/metaparse/v1/fwd/string.hpp>
-#include <boost/metaparse/v1/impl/update_c.hpp>
-#include <boost/metaparse/v1/impl/size.hpp>
+#include <boost/metaparse/v1/cpp98/fwd/string.hpp>
+#include <boost/metaparse/v1/cpp98/impl/update_c.hpp>
+#include <boost/metaparse/v1/cpp98/impl/size.hpp>
namespace boost
{
@@ -22,15 +21,10 @@ namespace boost
template <class S, char C>
struct push_back_c;
-#ifdef BOOST_METAPARSE_VARIADIC_STRING
- template <char... Cs, char C>
- struct push_back_c<string<Cs...>, C> : string<Cs..., C> {};
-#else
template <class S, char C>
struct push_back_c :
update_c<typename S::type, size<typename S::type>::type::value, C>
{};
-#endif
}
}
}
diff --git a/boost/metaparse/v1/impl/push_front_c.hpp b/boost/metaparse/v1/cpp98/impl/push_front_c.hpp
index 27d0d3c7c9..0cf96a78a4 100644
--- a/boost/metaparse/v1/impl/push_front_c.hpp
+++ b/boost/metaparse/v1/cpp98/impl/push_front_c.hpp
@@ -1,13 +1,12 @@
-#ifndef BOOST_METAPARSE_V1_IMPL_PUSH_FRONT_C_HPP
-#define BOOST_METAPARSE_V1_IMPL_PUSH_FRONT_C_HPP
+#ifndef BOOST_METAPARSE_V1_CPP98_IMPL_PUSH_FRONT_C_HPP
+#define BOOST_METAPARSE_V1_CPP98_IMPL_PUSH_FRONT_C_HPP
// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
-#include <boost/metaparse/config.hpp>
-#include <boost/metaparse/v1/fwd/string.hpp>
+#include <boost/metaparse/v1/cpp98/fwd/string.hpp>
#include <boost/preprocessor/arithmetic/dec.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
@@ -23,10 +22,6 @@ namespace boost
template <class S, char C>
struct push_front_c;
-#ifdef BOOST_METAPARSE_VARIADIC_STRING
- template <char... Cs, char C>
- struct push_front_c<string<Cs...>, C> : string<C, Cs...> {};
-#else
template <
BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int C),
char Ch
@@ -43,7 +38,6 @@ namespace boost
)
>
{};
-#endif
}
}
}
diff --git a/boost/metaparse/v1/impl/size.hpp b/boost/metaparse/v1/cpp98/impl/size.hpp
index c6e0ee7e27..7de124132a 100644
--- a/boost/metaparse/v1/impl/size.hpp
+++ b/boost/metaparse/v1/cpp98/impl/size.hpp
@@ -1,13 +1,12 @@
-#ifndef BOOST_METAPARSE_V1_IMPL_SIZE_HPP
-#define BOOST_METAPARSE_V1_IMPL_SIZE_HPP
+#ifndef BOOST_METAPARSE_V1_CPP98_IMPL_SIZE_HPP
+#define BOOST_METAPARSE_V1_CPP98_IMPL_SIZE_HPP
// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
-#include <boost/metaparse/config.hpp>
-#include <boost/metaparse/v1/fwd/string.hpp>
+#include <boost/metaparse/v1/cpp98/fwd/string.hpp>
#include <boost/mpl/int.hpp>
@@ -29,10 +28,6 @@ namespace boost
template <class S>
struct size;
-#ifdef BOOST_METAPARSE_VARIADIC_STRING
- template <char... Cs>
- struct size<string<Cs...>> : boost::mpl::int_<sizeof...(Cs)> {};
-#else
#ifdef BOOST_METAPARSE_STRING_CASE
# error BOOST_METAPARSE_STRING_CASE
#endif
@@ -59,7 +54,6 @@ namespace boost
)
#undef BOOST_METAPARSE_STRING_CASE
-#endif
}
}
}
diff --git a/boost/metaparse/v1/impl/update_c.hpp b/boost/metaparse/v1/cpp98/impl/update_c.hpp
index 5553933e95..367f79dc35 100644
--- a/boost/metaparse/v1/impl/update_c.hpp
+++ b/boost/metaparse/v1/cpp98/impl/update_c.hpp
@@ -1,15 +1,12 @@
-#ifndef BOOST_METAPARSE_V1_IMPL_UPDATE_C_HPP
-#define BOOST_METAPARSE_V1_IMPL_UPDATE_C_HPP
+#ifndef BOOST_METAPARSE_V1_CPP98_IMPL_UPDATE_C_HPP
+#define BOOST_METAPARSE_V1_CPP98_IMPL_UPDATE_C_HPP
// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
-#include <boost/metaparse/config.hpp>
-#include <boost/metaparse/v1/fwd/string.hpp>
-#include <boost/metaparse/v1/impl/split_at_c.hpp>
-#include <boost/metaparse/v1/impl/concat.hpp>
+#include <boost/metaparse/v1/cpp98/fwd/string.hpp>
#include <boost/preprocessor/arithmetic/dec.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
@@ -27,7 +24,6 @@ namespace boost
{
namespace impl
{
-#ifndef BOOST_METAPARSE_VARIADIC_STRING
template <class S, int N, int C>
struct update_c;
@@ -69,21 +65,6 @@ namespace boost
#undef BOOST_METAPARSE_UPDATE
#undef BOOST_METAPARSE_ARGN
-#else
- template <class S, int N, char C>
- struct update_c :
- concat<
- typename split_at_c<N, S>::type::first,
- typename
- update_c<typename split_at_c<N, S>::type::second, 0, C>::type
- >
- {};
-
- template <char... Cs, char C, char NewChar>
- struct update_c<string<C, Cs...>, 0, NewChar> :
- string<NewChar, Cs...>
- {};
-#endif
}
}
}
diff --git a/boost/metaparse/v1/cpp98/string.hpp b/boost/metaparse/v1/cpp98/string.hpp
new file mode 100644
index 0000000000..3f7ad7a555
--- /dev/null
+++ b/boost/metaparse/v1/cpp98/string.hpp
@@ -0,0 +1,272 @@
+#ifndef BOOST_METAPARSE_V1_CPP98_STRING_HPP
+#define BOOST_METAPARSE_V1_CPP98_STRING_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
+
+#include <boost/metaparse/v1/cpp98/fwd/string.hpp>
+#include <boost/metaparse/v1/string_tag.hpp>
+#include <boost/metaparse/v1/impl/string_iterator.hpp>
+#include <boost/metaparse/v1/cpp98/impl/empty_string.hpp>
+#include <boost/metaparse/v1/cpp98/impl/size.hpp>
+#include <boost/metaparse/v1/cpp98/impl/pop_front.hpp>
+#include <boost/metaparse/v1/cpp98/impl/push_front_c.hpp>
+#include <boost/metaparse/v1/cpp98/impl/push_back_c.hpp>
+#include <boost/metaparse/v1/cpp98/impl/pop_back.hpp>
+
+#include <boost/preprocessor/arithmetic/sub.hpp>
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+#include <boost/preprocessor/tuple/eat.hpp>
+
+#include <boost/type_traits/is_same.hpp>
+
+/*
+ * The string type
+ */
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int C)>
+ struct string
+ {
+ typedef string type;
+ typedef string_tag tag;
+ };
+ }
+ }
+}
+
+/*
+ * Boost.MPL overloads
+ */
+
+namespace boost
+{
+ namespace mpl
+ {
+ // push_back
+ template <class S>
+ struct push_back_impl;
+
+ template <>
+ struct push_back_impl<boost::metaparse::v1::string_tag>
+ {
+ typedef push_back_impl type;
+
+ template <class S, class C>
+ struct apply :
+ boost::metaparse::v1::impl::push_back_c<
+ typename S::type,
+ C::type::value
+ >
+ {};
+ };
+
+ // pop_back
+ template <class S>
+ struct pop_back_impl;
+
+ template <>
+ struct pop_back_impl<boost::metaparse::v1::string_tag>
+ {
+ typedef pop_back_impl type;
+
+ template <class S>
+ struct apply : boost::metaparse::v1::impl::pop_back<S> {};
+ };
+
+ // push_front
+ template <class S>
+ struct push_front_impl;
+
+ template <>
+ struct push_front_impl<boost::metaparse::v1::string_tag>
+ {
+ typedef push_front_impl type;
+
+ template <class S, class C>
+ struct apply :
+ boost::metaparse::v1::impl::push_front_c<
+ typename S::type,
+ C::type::value
+ >
+ {};
+ };
+
+ // pop_front
+ template <class S>
+ struct pop_front_impl;
+
+ template <>
+ struct pop_front_impl<boost::metaparse::v1::string_tag>
+ {
+ typedef pop_front_impl type;
+
+ template <class S>
+ struct apply : boost::metaparse::v1::impl::pop_front<S> {};
+ };
+
+ // clear
+ template <class S>
+ struct clear_impl;
+
+ template <>
+ struct clear_impl<boost::metaparse::v1::string_tag>
+ {
+ typedef clear_impl type;
+
+ template <class S>
+ struct apply : boost::metaparse::v1::string<> {};
+ };
+
+ // begin
+ template <class S>
+ struct begin_impl;
+
+ template <>
+ struct begin_impl<boost::metaparse::v1::string_tag>
+ {
+ typedef begin_impl type;
+
+ template <class S>
+ struct apply :
+ boost::metaparse::v1::impl::string_iterator<typename S::type, 0>
+ {};
+ };
+
+ // end
+ template <class S>
+ struct end_impl;
+
+ template <>
+ struct end_impl<boost::metaparse::v1::string_tag>
+ {
+ typedef end_impl type;
+
+ template <class S>
+ struct apply :
+ boost::metaparse::v1::impl::string_iterator<
+ typename S::type,
+ boost::metaparse::v1::impl::size<typename S::type>::type::value
+ >
+ {};
+ };
+
+ // equal_to
+ template <class A, class B>
+ struct equal_to_impl;
+
+ template <>
+ struct equal_to_impl<
+ boost::metaparse::v1::string_tag,
+ boost::metaparse::v1::string_tag
+ >
+ {
+ typedef equal_to_impl type;
+
+ template <class A, class B>
+ struct apply : boost::is_same<typename A::type, typename B::type> {};
+ };
+
+ template <class T>
+ struct equal_to_impl<boost::metaparse::v1::string_tag, T>
+ {
+ typedef equal_to_impl type;
+
+ template <class, class>
+ struct apply : false_ {};
+ };
+
+ template <class T>
+ struct equal_to_impl<T, boost::metaparse::v1::string_tag> :
+ equal_to_impl<boost::metaparse::v1::string_tag, T>
+ {};
+
+ // c_str
+ template <class S>
+ struct c_str;
+
+ template <BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int C)>
+ struct c_str<
+ boost::metaparse::v1::string<
+ BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, C)
+ >
+ >
+ {
+ typedef c_str type;
+ static const char value[BOOST_METAPARSE_LIMIT_STRING_SIZE + 1];
+ };
+
+ template <BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int C)>
+ const char
+ c_str<
+ boost::metaparse::v1::string<
+ BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, C)
+ >
+ >::value[BOOST_METAPARSE_LIMIT_STRING_SIZE + 1]
+ = {BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, C), 0};
+
+ template <>
+ struct c_str<boost::metaparse::v1::string<> > :
+ boost::metaparse::v1::impl::empty_string<>
+ {
+ typedef c_str type;
+ };
+
+ #ifdef BOOST_METAPARSE_STRING_CASE
+ # error BOOST_METAPARSE_STRING_CASE is already defined
+ #endif
+ #define BOOST_METAPARSE_STRING_CASE(z, n, unused) \
+ template <BOOST_PP_ENUM_PARAMS(n, int C)> \
+ struct \
+ c_str< \
+ boost::metaparse::v1::string< \
+ BOOST_PP_ENUM_PARAMS(n, C) BOOST_PP_COMMA_IF(n) \
+ BOOST_PP_ENUM( \
+ BOOST_PP_SUB(BOOST_METAPARSE_LIMIT_STRING_SIZE, n), \
+ BOOST_NO_CHAR BOOST_PP_TUPLE_EAT(3), \
+ ~ \
+ ) \
+ > \
+ > \
+ { \
+ typedef c_str type; \
+ static const char value[n + 1]; \
+ }; \
+ \
+ template <BOOST_PP_ENUM_PARAMS(n, int C)> \
+ const char c_str< \
+ boost::metaparse::v1::string< \
+ BOOST_PP_ENUM_PARAMS(n, C) BOOST_PP_COMMA_IF(n) \
+ BOOST_PP_ENUM( \
+ BOOST_PP_SUB(BOOST_METAPARSE_LIMIT_STRING_SIZE, n), \
+ BOOST_NO_CHAR BOOST_PP_TUPLE_EAT(3), \
+ ~ \
+ ) \
+ > \
+ >::value[n + 1] = {BOOST_PP_ENUM_PARAMS(n, C) BOOST_PP_COMMA_IF(n) 0};
+
+ BOOST_PP_REPEAT_FROM_TO(
+ 1,
+ BOOST_METAPARSE_LIMIT_STRING_SIZE,
+ BOOST_METAPARSE_STRING_CASE,
+ ~
+ )
+
+ #undef BOOST_METAPARSE_STRING_CASE
+ }
+}
+
+#define BOOST_METAPARSE_V1_CONFIG_NO_BOOST_METAPARSE_STRING 1
+
+#endif
+
diff --git a/boost/metaparse/v1/fwd/string.hpp b/boost/metaparse/v1/fwd/string.hpp
index b5ecbd21e4..ea769d1bcd 100644
--- a/boost/metaparse/v1/fwd/string.hpp
+++ b/boost/metaparse/v1/fwd/string.hpp
@@ -1,38 +1,18 @@
#ifndef BOOST_METAPARSE_V1_FWD_STRING_HPP
#define BOOST_METAPARSE_V1_FWD_STRING_HPP
-// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
#include <boost/metaparse/config.hpp>
-#include <boost/metaparse/limit_string_size.hpp>
-#include <boost/metaparse/v1/impl/no_char.hpp>
-#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
-namespace boost
-{
- namespace metaparse
- {
- namespace v1
- {
-#ifdef BOOST_METAPARSE_VARIADIC_STRING
- template <char... Cs>
- struct string;
+#if BOOST_METAPARSE_STD >= 2011
+# include <boost/metaparse/v1/cpp11/fwd/string.hpp>
#else
- template <
- BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
- BOOST_METAPARSE_LIMIT_STRING_SIZE,
- int C,
- BOOST_NO_CHAR
- )
- >
- struct string;
+# include <boost/metaparse/v1/cpp98/fwd/string.hpp>
#endif
- }
- }
-}
#endif
diff --git a/boost/metaparse/v1/impl/at_c.hpp b/boost/metaparse/v1/impl/at_c.hpp
index af7177410e..007ae18255 100644
--- a/boost/metaparse/v1/impl/at_c.hpp
+++ b/boost/metaparse/v1/impl/at_c.hpp
@@ -7,60 +7,12 @@
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/metaparse/config.hpp>
-#include <boost/metaparse/v1/fwd/string.hpp>
-#include <boost/mpl/char.hpp>
-
-#include <boost/preprocessor/repetition/enum_params.hpp>
-#include <boost/preprocessor/repetition/repeat.hpp>
-
-namespace boost
-{
- namespace metaparse
- {
- namespace v1
- {
- namespace impl
- {
- template <class S, int N>
- struct at_c;
-
-#ifdef BOOST_METAPARSE_VARIADIC_STRING
- template <char C, char... Cs, int N>
- struct at_c<string<C, Cs...>, N> : at_c<string<Cs...>, N - 1> {};
-
- template <char C, char... Cs>
- struct at_c<string<C, Cs...>, 0> : boost::mpl::char_<C> {};
+#if BOOST_METAPARSE_STD >= 2011
+# include <boost/metaparse/v1/cpp11/impl/at_c.hpp>
#else
- #ifdef BOOST_METAPARSE_STRING_CASE
- # error BOOST_METAPARSE_STRING_CASE is already defined
- #endif
- #define BOOST_METAPARSE_STRING_CASE(z, n, unused) \
- template < \
- BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int C) \
- > \
- struct \
- at_c< \
- string< \
- BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, C) \
- >, \
- n \
- > : \
- boost::mpl::char_<BOOST_PP_CAT(C, n)> \
- {};
-
- BOOST_PP_REPEAT(
- BOOST_METAPARSE_LIMIT_STRING_SIZE,
- BOOST_METAPARSE_STRING_CASE,
- ~
- )
-
- #undef BOOST_METAPARSE_STRING_CASE
+# include <boost/metaparse/v1/cpp98/impl/at_c.hpp>
#endif
- }
- }
- }
-}
#endif
diff --git a/boost/metaparse/v1/impl/concat.hpp b/boost/metaparse/v1/impl/concat.hpp
deleted file mode 100644
index d866ae42b1..0000000000
--- a/boost/metaparse/v1/impl/concat.hpp
+++ /dev/null
@@ -1,106 +0,0 @@
-#ifndef BOOST_METAPARSE_V1_IMPL_CONCAT_HPP
-#define BOOST_METAPARSE_V1_IMPL_CONCAT_HPP
-
-// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
-
-#include <boost/metaparse/config.hpp>
-#include <boost/metaparse/v1/fwd/string.hpp>
-
-#include <boost/preprocessor/arithmetic/dec.hpp>
-#include <boost/preprocessor/arithmetic/inc.hpp>
-#include <boost/preprocessor/arithmetic/mul.hpp>
-#include <boost/preprocessor/arithmetic/sub.hpp>
-#include <boost/preprocessor/cat.hpp>
-#include <boost/preprocessor/punctuation/comma_if.hpp>
-#include <boost/preprocessor/repetition/enum.hpp>
-#include <boost/preprocessor/repetition/enum_params.hpp>
-
-namespace boost
-{
- namespace metaparse
- {
- namespace v1
- {
- namespace impl
- {
- template <class A, class B>
- struct concat;
-
-#ifdef BOOST_METAPARSE_VARIADIC_STRING
- template <char... As, char... Bs>
- struct concat<string<As...>, string<Bs...>> : string<As..., Bs...> {};
-#else
- template <class A, class B>
- struct concat_impl;
-
- #ifdef BOOST_METAPARSE_ARG
- # error BOOST_METAPARSE_ARG already defined
- #endif
- #define BOOST_METAPARSE_ARG(z, n, unused) \
- BOOST_PP_CAT(B, BOOST_PP_INC(n))
-
- #ifdef BOOST_METAPARSE_CONCAT
- # error BOOST_METAPARSE_CONCAT already defined
- #endif
- #define BOOST_METAPARSE_CONCAT(z, n, unused) \
- template < \
- BOOST_PP_ENUM_PARAMS(n, int A) BOOST_PP_COMMA_IF(n) \
- BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int B) \
- > \
- struct \
- concat_impl< \
- string< \
- BOOST_PP_ENUM_PARAMS(n, A) \
- BOOST_PP_COMMA_IF( \
- BOOST_PP_MUL( \
- BOOST_PP_SUB(BOOST_METAPARSE_LIMIT_STRING_SIZE, n), \
- n \
- ) \
- ) \
- BOOST_PP_ENUM( \
- BOOST_PP_SUB(BOOST_METAPARSE_LIMIT_STRING_SIZE, n), \
- BOOST_NO_CHAR BOOST_PP_TUPLE_EAT(3), \
- ~ \
- ) \
- >, \
- string< \
- BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, B) \
- > \
- > : \
- concat< \
- string<BOOST_PP_ENUM_PARAMS(n, A) BOOST_PP_COMMA_IF(n) B0>, \
- string< \
- BOOST_PP_ENUM( \
- BOOST_PP_DEC(BOOST_METAPARSE_LIMIT_STRING_SIZE), \
- BOOST_METAPARSE_ARG, \
- ~ \
- ) \
- > \
- > \
- {};
-
- BOOST_PP_REPEAT(
- BOOST_METAPARSE_LIMIT_STRING_SIZE,
- BOOST_METAPARSE_CONCAT,
- ~
- )
-
- #undef BOOST_METAPARSE_ARG
- #undef BOOST_METAPARSE_CONCAT
-
- template <class S>
- struct concat<S, string<> > : S {};
-
- template <class A, class B>
- struct concat : concat_impl<A, B> {};
-#endif
- }
- }
- }
-}
-
-#endif
-
diff --git a/boost/metaparse/v1/impl/empty_string.hpp b/boost/metaparse/v1/impl/empty_string.hpp
deleted file mode 100644
index 7b62496450..0000000000
--- a/boost/metaparse/v1/impl/empty_string.hpp
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef BOOST_METAPARSE_V1_IMPL_EMPTY_STRING_HPP
-#define BOOST_METAPARSE_V1_IMPL_EMPTY_STRING_HPP
-
-// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
-
-#include <boost/metaparse/config.hpp>
-
-namespace boost
-{
- namespace metaparse
- {
- namespace v1
- {
- namespace impl
- {
- template <class Ignore = int>
- struct empty_string
- {
- typedef empty_string type;
-
- #ifdef BOOST_NO_CONSTEXPR_C_STR
- static const char value[1];
- #else
- static constexpr char value[1] = {0};
- #endif
- };
-
- #ifdef BOOST_NO_CONSTEXPR_C_STR
- template <class Ignore>
- const char empty_string<Ignore>::value[1] = {0};
- #else
- template <class Ignore>
- constexpr char empty_string<Ignore>::value[1];
- #endif
- }
- }
- }
-}
-
-#endif
-
diff --git a/boost/metaparse/v1/impl/split_at_c.hpp b/boost/metaparse/v1/impl/split_at_c.hpp
deleted file mode 100644
index 8a5a1a3618..0000000000
--- a/boost/metaparse/v1/impl/split_at_c.hpp
+++ /dev/null
@@ -1,99 +0,0 @@
-#ifndef BOOST_METAPARSE_V1_IMPL_SPLIT_AT_C_HPP
-#define BOOST_METAPARSE_V1_IMPL_SPLIT_AT_C_HPP
-
-// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
-
-#include <boost/metaparse/config.hpp>
-#include <boost/metaparse/v1/fwd/string.hpp>
-#include <boost/metaparse/v1/impl/push_front_c.hpp>
-
-#include <boost/preprocessor/arithmetic/add.hpp>
-#include <boost/preprocessor/arithmetic/sub.hpp>
-#include <boost/preprocessor/cat.hpp>
-#include <boost/preprocessor/repetition/enum.hpp>
-#include <boost/preprocessor/repetition/enum_params.hpp>
-#include <boost/preprocessor/repetition/repeat.hpp>
-
-#include <boost/mpl/pair.hpp>
-
-namespace boost
-{
- namespace metaparse
- {
- namespace v1
- {
- namespace impl
- {
- template <int N, class S>
- struct split_at_c;
-
-#ifdef BOOST_METAPARSE_VARIADIC_STRING
- template <int N, char C, char... Cs>
- struct split_at_c<N, string<C, Cs...>> :
- boost::mpl::pair<
- typename push_front_c<
- typename split_at_c<N - 1, string<Cs...>>::type::first,
- C
- >::type,
- typename split_at_c<N - 1, string<Cs...>>::type::second
- >
- {};
-
- template <char C, char... Cs>
- struct split_at_c<0, string<C, Cs...>> :
- boost::mpl::pair<string<>, string<C, Cs...>>
- {};
-
- template <class S>
- struct split_at_c<0, S> : boost::mpl::pair<string<>, S> {};
-#else
- #ifdef BOOST_METAPARSE_ARG
- # error BOOST_METAPARSE_ARG already defined
- #endif
- #define BOOST_METAPARSE_ARG(z, n, d) BOOST_PP_CAT(C, BOOST_PP_ADD(n, d))
-
- #ifdef BOOST_METAPARSE_SPLIT_AT
- # error BOOST_METAPARSE_SPLIT_AT already defined
- #endif
- #define BOOST_METAPARSE_SPLIT_AT(z, n, unused) \
- template < \
- BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int C) \
- > \
- struct \
- split_at_c< \
- n, \
- string<BOOST_PP_ENUM_PARAMS( \
- BOOST_METAPARSE_LIMIT_STRING_SIZE, C) \
- > \
- > : \
- boost::mpl::pair< \
- string<BOOST_PP_ENUM_PARAMS(n, C)>, \
- string< \
- BOOST_PP_ENUM( \
- BOOST_PP_SUB(BOOST_METAPARSE_LIMIT_STRING_SIZE, n), \
- BOOST_METAPARSE_ARG, \
- n \
- ) \
- > \
- > \
- {};
-
- BOOST_PP_REPEAT(
- BOOST_METAPARSE_LIMIT_STRING_SIZE,
- BOOST_METAPARSE_SPLIT_AT,
- ~
- )
-
- #undef BOOST_METAPARSE_SPLIT_AT
- #undef BOOST_METAPARSE_ARG
-#endif
- }
- }
- }
-}
-
-#endif
-
diff --git a/boost/metaparse/v1/string.hpp b/boost/metaparse/v1/string.hpp
index 6535d659d3..d8bb9f93e3 100644
--- a/boost/metaparse/v1/string.hpp
+++ b/boost/metaparse/v1/string.hpp
@@ -1,355 +1,17 @@
#ifndef BOOST_METAPARSE_V1_STRING_HPP
#define BOOST_METAPARSE_V1_STRING_HPP
-// Copyright Abel Sinkovics (abel@sinkovics.hu) 2012.
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
#include <boost/metaparse/config.hpp>
-#include <boost/metaparse/v1/fwd/string.hpp>
-#include <boost/metaparse/v1/string_tag.hpp>
-#include <boost/metaparse/v1/impl/string_iterator.hpp>
-#include <boost/metaparse/v1/impl/empty_string.hpp>
-#include <boost/metaparse/v1/impl/size.hpp>
-#include <boost/metaparse/v1/impl/pop_front.hpp>
-#include <boost/metaparse/v1/impl/push_front_c.hpp>
-#include <boost/metaparse/v1/impl/push_back_c.hpp>
-#include <boost/metaparse/v1/impl/pop_back.hpp>
-#include <boost/metaparse/v1/impl/assert_string_length.hpp>
-#include <boost/metaparse/v1/impl/string_at.hpp>
-#include <boost/preprocessor/arithmetic/sub.hpp>
-#include <boost/preprocessor/punctuation/comma_if.hpp>
-#include <boost/preprocessor/repetition/enum.hpp>
-#include <boost/preprocessor/repetition/enum_params.hpp>
-#include <boost/preprocessor/repetition/repeat_from_to.hpp>
-#include <boost/preprocessor/tuple/eat.hpp>
-
-#include <boost/type_traits/is_same.hpp>
-
-/*
- * The string type
- */
-
-namespace boost
-{
- namespace metaparse
- {
- namespace v1
- {
-#ifdef BOOST_METAPARSE_VARIADIC_STRING
- template <char... Cs>
- struct string
- {
- typedef string type;
- typedef string_tag tag;
- };
+#if BOOST_METAPARSE_STD >= 2011
+# include <boost/metaparse/v1/cpp11/string.hpp>
#else
- template <BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int C)>
- struct string
- {
- typedef string type;
- typedef string_tag tag;
- };
-#endif
- }
- }
-}
-
-/*
- * Boost.MPL overloads
- */
-
-namespace boost
-{
- namespace mpl
- {
- // push_back
- template <class S>
- struct push_back_impl;
-
- template <>
- struct push_back_impl<boost::metaparse::v1::string_tag>
- {
- typedef push_back_impl type;
-
- template <class S, class C>
- struct apply :
- boost::metaparse::v1::impl::push_back_c<
- typename S::type,
- C::type::value
- >
- {};
- };
-
- // pop_back
- template <class S>
- struct pop_back_impl;
-
- template <>
- struct pop_back_impl<boost::metaparse::v1::string_tag>
- {
- typedef pop_back_impl type;
-
- template <class S>
- struct apply : boost::metaparse::v1::impl::pop_back<S> {};
- };
-
- // push_front
- template <class S>
- struct push_front_impl;
-
- template <>
- struct push_front_impl<boost::metaparse::v1::string_tag>
- {
- typedef push_front_impl type;
-
- template <class S, class C>
- struct apply :
- boost::metaparse::v1::impl::push_front_c<
- typename S::type,
- C::type::value
- >
- {};
- };
-
- // pop_front
- template <class S>
- struct pop_front_impl;
-
- template <>
- struct pop_front_impl<boost::metaparse::v1::string_tag>
- {
- typedef pop_front_impl type;
-
- template <class S>
- struct apply : boost::metaparse::v1::impl::pop_front<S> {};
- };
-
- // clear
- template <class S>
- struct clear_impl;
-
- template <>
- struct clear_impl<boost::metaparse::v1::string_tag>
- {
- typedef clear_impl type;
-
- template <class S>
- struct apply : boost::metaparse::v1::string<> {};
- };
-
- // begin
- template <class S>
- struct begin_impl;
-
- template <>
- struct begin_impl<boost::metaparse::v1::string_tag>
- {
- typedef begin_impl type;
-
- template <class S>
- struct apply :
- boost::metaparse::v1::impl::string_iterator<typename S::type, 0>
- {};
- };
-
- // end
- template <class S>
- struct end_impl;
-
- template <>
- struct end_impl<boost::metaparse::v1::string_tag>
- {
- typedef end_impl type;
-
- template <class S>
- struct apply :
- boost::metaparse::v1::impl::string_iterator<
- typename S::type,
- boost::metaparse::v1::impl::size<typename S::type>::type::value
- >
- {};
- };
-
- // equal_to
- template <class A, class B>
- struct equal_to_impl;
-
- template <>
- struct equal_to_impl<
- boost::metaparse::v1::string_tag,
- boost::metaparse::v1::string_tag
- >
- {
- typedef equal_to_impl type;
-
- template <class A, class B>
- struct apply : boost::is_same<typename A::type, typename B::type> {};
- };
-
- template <class T>
- struct equal_to_impl<boost::metaparse::v1::string_tag, T>
- {
- typedef equal_to_impl type;
-
- template <class, class>
- struct apply : false_ {};
- };
-
- template <class T>
- struct equal_to_impl<T, boost::metaparse::v1::string_tag> :
- equal_to_impl<boost::metaparse::v1::string_tag, T>
- {};
-
- // c_str
- template <class S>
- struct c_str;
-
-#ifdef BOOST_METAPARSE_VARIADIC_STRING
- template <char... Cs>
- struct c_str<boost::metaparse::v1::string<Cs...>>
- {
- typedef c_str type;
- #ifdef BOOST_NO_CONSTEXPR_C_STR
- static const char value[sizeof...(Cs) + 1];
- #else
- static constexpr char value[sizeof...(Cs) + 1] = {Cs..., 0};
- #endif
- };
-
- template <>
- struct c_str<boost::metaparse::v1::string<>> :
- boost::metaparse::v1::impl::empty_string<>
- {};
-
- #ifdef BOOST_NO_CONSTEXPR_C_STR
- template <char... Cs>
- const char c_str<boost::metaparse::v1::string<Cs...>>::value[]
- = {Cs..., 0};
- #else
- template <char... Cs>
- constexpr char c_str<boost::metaparse::v1::string<Cs...>>::value[];
- #endif
-
-#else
- template <BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int C)>
- struct c_str<
- boost::metaparse::v1::string<
- BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, C)
- >
- >
- {
- typedef c_str type;
- static BOOST_CONSTEXPR const char
- value[BOOST_METAPARSE_LIMIT_STRING_SIZE + 1]
- #if !defined BOOST_NO_CONSTEXPR && !defined BOOST_NO_CXX11_CONSTEXPR
- = {BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, C), 0}
- #endif
- ;
- };
-
- template <BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int C)>
- BOOST_CONSTEXPR const char
- c_str<
- boost::metaparse::v1::string<
- BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, C)
- >
- >::value[BOOST_METAPARSE_LIMIT_STRING_SIZE + 1]
- #if defined BOOST_NO_CONSTEXPR || defined BOOST_NO_CXX11_CONSTEXPR
- = {BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, C), 0}
- #endif
- ;
-
- template <>
- struct c_str<boost::metaparse::v1::string<> > :
- boost::metaparse::v1::impl::empty_string<>
- {
- typedef c_str type;
- };
-
- #ifdef BOOST_METAPARSE_DEF
- # error BOOST_METAPARSE_DEF already defined
- #endif
- #define BOOST_METAPARSE_DEF(n) \
- = {BOOST_PP_ENUM_PARAMS(n, C) BOOST_PP_COMMA_IF(n) 0}
-
- #ifdef BOOST_METAPARSE_STRING_DECLARE
- # error BOOST_METAPARSE_STRING_DECLARE already defined
- #endif
- #ifdef BOOST_METAPARSE_STRING_DEFINE
- # error BOOST_METAPARSE_STRING_DECLARE already defined
- #endif
- #if !defined BOOST_NO_CONSTEXPR && !defined BOOST_NO_CXX11_CONSTEXPR
- # define BOOST_METAPARSE_STRING_DECLARE(n) BOOST_METAPARSE_DEF(n)
- # define BOOST_METAPARSE_STRING_DEFINE(n)
- #else
- # define BOOST_METAPARSE_STRING_DECLARE(n)
- # define BOOST_METAPARSE_STRING_DEFINE(n) BOOST_METAPARSE_DEF(n)
- #endif
-
- #ifdef BOOST_METAPARSE_STRING_CASE
- # error BOOST_METAPARSE_STRING_CASE is already defined
- #endif
- #define BOOST_METAPARSE_STRING_CASE(z, n, unused) \
- template <BOOST_PP_ENUM_PARAMS(n, int C)> \
- struct \
- c_str< \
- boost::metaparse::v1::string< \
- BOOST_PP_ENUM_PARAMS(n, C) BOOST_PP_COMMA_IF(n) \
- BOOST_PP_ENUM( \
- BOOST_PP_SUB(BOOST_METAPARSE_LIMIT_STRING_SIZE, n), \
- BOOST_NO_CHAR BOOST_PP_TUPLE_EAT(3), \
- ~ \
- ) \
- > \
- > \
- { \
- typedef c_str type; \
- static BOOST_CONSTEXPR const char value[n + 1] \
- BOOST_METAPARSE_STRING_DECLARE(n); \
- }; \
- \
- template <BOOST_PP_ENUM_PARAMS(n, int C)> \
- BOOST_CONSTEXPR const char c_str< \
- boost::metaparse::v1::string< \
- BOOST_PP_ENUM_PARAMS(n, C) BOOST_PP_COMMA_IF(n) \
- BOOST_PP_ENUM( \
- BOOST_PP_SUB(BOOST_METAPARSE_LIMIT_STRING_SIZE, n), \
- BOOST_NO_CHAR BOOST_PP_TUPLE_EAT(3), \
- ~ \
- ) \
- > \
- >::value[n + 1] BOOST_METAPARSE_STRING_DEFINE(n);
-
- BOOST_PP_REPEAT_FROM_TO(
- 1,
- BOOST_METAPARSE_LIMIT_STRING_SIZE,
- BOOST_METAPARSE_STRING_CASE,
- ~
- )
-
- #undef BOOST_METAPARSE_STRING_CASE
- #undef BOOST_METAPARSE_STRING_DECLARE
- #undef BOOST_METAPARSE_STRING_DEFINE
- #undef BOOST_METAPARSE_DEF
-#endif
- }
-}
-
-#include <boost/metaparse/v1/impl/remove_trailing_no_chars.hpp>
-
-#if \
- defined BOOST_METAPARSE_VARIADIC_STRING \
- && !defined BOOST_NO_CONSTEXPR && !defined BOOST_NO_CXX11_CONSTEXPR
-
-# include <boost/metaparse/v1/impl/string.hpp>
-
-#else
-
-# define BOOST_METAPARSE_V1_CONFIG_NO_BOOST_METAPARSE_STRING 1
-
+# include <boost/metaparse/v1/cpp98/string.hpp>
#endif
#endif
diff --git a/boost/move/algo/adaptive_sort.hpp b/boost/move/algo/adaptive_sort.hpp
index 6b5586e587..c96ab2d78b 100644
--- a/boost/move/algo/adaptive_sort.hpp
+++ b/boost/move/algo/adaptive_sort.hpp
@@ -43,18 +43,25 @@ namespace movelib {
//! ceil(sqrt(std::distance(first, last)))*2.
//!
//! <b>Caution</b>: Experimental implementation, not production-ready.
-template<class RandIt, class Compare>
+template<class RandIt, class RandRawIt, class Compare>
void adaptive_sort( RandIt first, RandIt last, Compare comp
- , typename iterator_traits<RandIt>::value_type* uninitialized = 0
- , std::size_t uninitialized_len = 0)
+ , RandRawIt uninitialized
+ , std::size_t uninitialized_len)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
typedef typename iterator_traits<RandIt>::value_type value_type;
- ::boost::movelib::detail_adaptive::adaptive_xbuf<value_type> xbuf(uninitialized, uninitialized_len);
+ ::boost::movelib::detail_adaptive::adaptive_xbuf<value_type, RandRawIt> xbuf(uninitialized, uninitialized_len);
::boost::movelib::detail_adaptive::adaptive_sort_impl(first, size_type(last - first), comp, xbuf);
}
+template<class RandIt, class Compare>
+void adaptive_sort( RandIt first, RandIt last, Compare comp)
+{
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+ adaptive_sort(first, last, comp, (value_type*)0, 0u);
+}
+
} //namespace movelib {
} //namespace boost {
diff --git a/boost/move/algo/detail/adaptive_sort_merge.hpp b/boost/move/algo/detail/adaptive_sort_merge.hpp
index 63b3f45979..60b5e7b06c 100644
--- a/boost/move/algo/detail/adaptive_sort_merge.hpp
+++ b/boost/move/algo/detail/adaptive_sort_merge.hpp
@@ -154,20 +154,20 @@ typename iterator_traits<ForwardIt>::size_type
return count;
}
-template<class T>
+template<class T, class RandRawIt = T*>
class adaptive_xbuf
{
adaptive_xbuf(const adaptive_xbuf &);
adaptive_xbuf & operator=(const adaptive_xbuf &);
public:
- typedef T* iterator;
+ typedef RandRawIt iterator;
adaptive_xbuf()
- : m_ptr(0), m_size(0), m_capacity(0)
+ : m_ptr(), m_size(0), m_capacity(0)
{}
- adaptive_xbuf(T *raw_memory, std::size_t capacity)
+ adaptive_xbuf(RandRawIt raw_memory, std::size_t capacity)
: m_ptr(raw_memory), m_size(0), m_capacity(capacity)
{}
@@ -183,7 +183,7 @@ class adaptive_xbuf
m_size = n;
}
else{
- T *result = boost::move(first, first+m_size, m_ptr);
+ RandRawIt result = boost::move(first, first+m_size, m_ptr);
boost::uninitialized_move(first+m_size, first+n, result);
m_size = n;
}
@@ -201,8 +201,8 @@ class adaptive_xbuf
iterator add(RandIt it)
{
BOOST_ASSERT(m_size < m_capacity);
- T * p_ret = m_ptr + m_size;
- ::new(p_ret) T(::boost::move(*it));
+ RandRawIt p_ret = m_ptr + m_size;
+ ::new(&*p_ret) T(::boost::move(*it));
++m_size;
return p_ret;
}
@@ -249,14 +249,26 @@ class adaptive_xbuf
}
}
+ private:
+ template<class RIt>
+ static bool is_raw_ptr(RIt)
+ {
+ return false;
+ }
+
+ static bool is_raw_ptr(T*)
+ {
+ return true;
+ }
+
+ public:
template<class U>
bool supports_aligned_trailing(std::size_t size, std::size_t trail_count) const
{
- if(this->data()){
- uintptr_t u_addr_sz = uintptr_t(this->data()+size);
- uintptr_t u_addr_cp = uintptr_t(this->data()+this->capacity());
+ if(this->is_raw_ptr(this->data()) && m_capacity){
+ uintptr_t u_addr_sz = uintptr_t(&*(this->data()+size));
+ uintptr_t u_addr_cp = uintptr_t(&*(this->data()+this->capacity()));
u_addr_sz = ((u_addr_sz + sizeof(U)-1)/sizeof(U))*sizeof(U);
-
return (u_addr_cp >= u_addr_sz) && ((u_addr_cp - u_addr_sz)/sizeof(U) >= trail_count);
}
return false;
@@ -271,7 +283,7 @@ class adaptive_xbuf
template<class U>
U *aligned_trailing(std::size_t pos) const
{
- uintptr_t u_addr = uintptr_t(this->data()+pos);
+ uintptr_t u_addr = uintptr_t(&*(this->data()+pos));
u_addr = ((u_addr + sizeof(U)-1)/sizeof(U))*sizeof(U);
return (U*)u_addr;
}
@@ -302,7 +314,7 @@ class adaptive_xbuf
}
private:
- T *m_ptr;
+ RandRawIt m_ptr;
std::size_t m_size;
std::size_t m_capacity;
};
@@ -458,7 +470,7 @@ RandIt partial_merge_bufferless_impl
if(first1 != last1 && comp(*last1, last1[-1])){
do{
RandIt const old_last1 = last1;
- last1 = lower_bound(last1, last2, *first1, comp);
+ last1 = boost::movelib::lower_bound(last1, last2, *first1, comp);
first1 = rotate_gcd(first1, old_last1, last1);//old_last1 == last1 supported
if(last1 == last2){
return first1;
@@ -604,13 +616,13 @@ void op_buffered_merge
size_type const len1 = size_type(middle-first);
size_type const len2 = size_type(last-middle);
if(len1 <= len2){
- first = upper_bound(first, middle, *middle, comp);
+ first = boost::movelib::upper_bound(first, middle, *middle, comp);
xbuf.move_assign(first, size_type(middle-first));
op_merge_with_right_placed
(xbuf.data(), xbuf.end(), first, middle, last, comp, op);
}
else{
- last = lower_bound(middle, last, middle[-1], comp);
+ last = boost::movelib::lower_bound(middle, last, middle[-1], comp);
xbuf.move_assign(middle, size_type(last-middle));
op_merge_with_left_placed
(first, middle, last, xbuf.data(), xbuf.end(), comp, op);
@@ -618,11 +630,11 @@ void op_buffered_merge
}
}
-template<class RandIt, class Compare>
+template<class RandIt, class Compare, class XBuf>
void buffered_merge
( RandIt first, RandIt const middle, RandIt last
, Compare comp
- , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> &xbuf)
+ , XBuf &xbuf)
{
op_buffered_merge(first, middle, last, comp, move_op(), xbuf);
}
@@ -633,15 +645,14 @@ void buffered_merge
// in the begining of the range, and ordered according to comp
//
// Returns the number of collected keys
-template<class RandIt, class Compare>
+template<class RandIt, class Compare, class XBuf>
typename iterator_traits<RandIt>::size_type
collect_unique
( RandIt const first, RandIt const last
, typename iterator_traits<RandIt>::size_type const max_collected, Compare comp
- , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf)
+ , XBuf & xbuf)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
- typedef typename iterator_traits<RandIt>::value_type value_type;
size_type h = 0;
if(max_collected){
++h; // first key is always here
@@ -650,9 +661,9 @@ typename iterator_traits<RandIt>::size_type
RandIt search_end = u;
if(xbuf.capacity() >= max_collected){
- value_type *const ph0 = xbuf.add(first);
+ typename XBuf::iterator const ph0 = xbuf.add(first);
while(u != last && h < max_collected){
- value_type * const r = lower_bound(ph0, xbuf.end(), *u, comp);
+ typename XBuf::iterator const r = boost::movelib::lower_bound(ph0, xbuf.end(), *u, comp);
//If key not found add it to [h, h+h0)
if(r == xbuf.end() || comp(*u, *r) ){
RandIt const new_h0 = boost::move(search_end, u, h0);
@@ -669,7 +680,7 @@ typename iterator_traits<RandIt>::size_type
}
else{
while(u != last && h < max_collected){
- RandIt const r = lower_bound(h0, search_end, *u, comp);
+ RandIt const r = boost::movelib::lower_bound(h0, search_end, *u, comp);
//If key not found add it to [h, h+h0)
if(r == search_end || comp(*u, *r) ){
RandIt const new_h0 = rotate_gcd(h0, search_end, u);
@@ -1666,14 +1677,14 @@ void op_merge_right_step_once
//
// As a last step, if auxiliary memory is available in-place merge is performed.
// until all is merged or auxiliary memory is not large enough.
-template<class RandIt, class Compare>
+template<class RandIt, class Compare, class XBuf>
typename iterator_traits<RandIt>::size_type
adaptive_sort_build_blocks
( RandIt const first
, typename iterator_traits<RandIt>::size_type const len
, typename iterator_traits<RandIt>::size_type const l_base
, typename iterator_traits<RandIt>::size_type const l_build_buf
- , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf
+ , XBuf & xbuf
, Compare comp)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
@@ -1820,7 +1831,7 @@ void adaptive_sort_combine_blocks
//Returns true if buffer is placed in
//[buffer+len-l_intbuf, buffer+len). Otherwise, buffer is
//[buffer,buffer+l_intbuf)
-template<class RandIt, class Compare>
+template<class RandIt, class Compare, class XBuf>
bool adaptive_sort_combine_all_blocks
( RandIt keys
, typename iterator_traits<RandIt>::size_type &n_keys
@@ -1828,7 +1839,7 @@ bool adaptive_sort_combine_all_blocks
, typename iterator_traits<RandIt>::size_type const l_buf_plus_data
, typename iterator_traits<RandIt>::size_type l_merged
, typename iterator_traits<RandIt>::size_type &l_intbuf
- , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf
+ , XBuf & xbuf
, Compare comp)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
@@ -1916,11 +1927,11 @@ bool adaptive_sort_combine_all_blocks
return buffer_right;
}
-template<class RandIt, class Compare>
+template<class RandIt, class Compare, class XBuf>
void stable_merge
( RandIt first, RandIt const middle, RandIt last
, Compare comp
- , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> &xbuf)
+ , XBuf &xbuf)
{
BOOST_ASSERT(xbuf.empty());
typedef typename iterator_traits<RandIt>::size_type size_type;
@@ -1937,13 +1948,13 @@ void stable_merge
}
-template<class RandIt, class Compare>
+template<class RandIt, class Compare, class XBuf>
void adaptive_sort_final_merge( bool buffer_right
, RandIt const first
, typename iterator_traits<RandIt>::size_type const l_intbuf
, typename iterator_traits<RandIt>::size_type const n_keys
, typename iterator_traits<RandIt>::size_type const len
- , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf
+ , XBuf & xbuf
, Compare comp)
{
//BOOST_ASSERT(n_keys || xbuf.size() == l_intbuf);
@@ -1973,11 +1984,11 @@ void adaptive_sort_final_merge( bool buffer_right
BOOST_MOVE_ADAPTIVE_SORT_PRINT(" After final_merge : ", len);
}
-template<class RandIt, class Compare, class Unsigned, class T>
+template<class RandIt, class Compare, class Unsigned, class XBuf>
bool adaptive_sort_build_params
(RandIt first, Unsigned const len, Compare comp
, Unsigned &n_keys, Unsigned &l_intbuf, Unsigned &l_base, Unsigned &l_build_buf
- , adaptive_xbuf<T> & xbuf
+ , XBuf & xbuf
)
{
typedef Unsigned size_type;
@@ -2064,7 +2075,7 @@ bool adaptive_sort_build_params
return true;
}
-template<class RandIt, class Compare>
+template<class RandIt, class Compare, class XBuf>
inline void adaptive_merge_combine_blocks( RandIt first
, typename iterator_traits<RandIt>::size_type len1
, typename iterator_traits<RandIt>::size_type len2
@@ -2074,7 +2085,7 @@ inline void adaptive_merge_combine_blocks( RandIt first
, bool use_internal_buf
, bool xbuf_used
, Compare comp
- , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf
+ , XBuf & xbuf
)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
@@ -2135,7 +2146,7 @@ inline void adaptive_merge_combine_blocks( RandIt first
}
}
-template<class RandIt, class Compare>
+template<class RandIt, class Compare, class XBuf>
inline void adaptive_merge_final_merge( RandIt first
, typename iterator_traits<RandIt>::size_type len1
, typename iterator_traits<RandIt>::size_type len2
@@ -2145,7 +2156,7 @@ inline void adaptive_merge_final_merge( RandIt first
, bool use_internal_buf
, bool xbuf_used
, Compare comp
- , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf
+ , XBuf & xbuf
)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
@@ -2270,12 +2281,12 @@ inline SizeType adaptive_merge_n_keys_intbuf(SizeType &rl_block, SizeType len1,
//
// * If auxiliary memory is available, the "build_blocks" will be extended to build bigger blocks
// using classic merge.
-template<class RandIt, class Compare>
+template<class RandIt, class Compare, class XBuf>
void adaptive_sort_impl
( RandIt first
, typename iterator_traits<RandIt>::size_type const len
, Compare comp
- , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf
+ , XBuf & xbuf
)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
@@ -2368,13 +2379,13 @@ void adaptive_sort_impl
// * If auxiliary memory is more than csqrtlen+n_keys*sizeof(std::size_t),
// then no csqrtlen need to be extracted and "combine_blocks" will use integral
// keys to combine blocks.
-template<class RandIt, class Compare>
+template<class RandIt, class Compare, class XBuf>
void adaptive_merge_impl
( RandIt first
, typename iterator_traits<RandIt>::size_type const len1
, typename iterator_traits<RandIt>::size_type const len2
, Compare comp
- , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf
+ , XBuf & xbuf
)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
diff --git a/boost/move/algo/detail/basic_op.hpp b/boost/move/algo/detail/basic_op.hpp
index a9369e07ba..ea5faf0e53 100644
--- a/boost/move/algo/detail/basic_op.hpp
+++ b/boost/move/algo/detail/basic_op.hpp
@@ -35,19 +35,19 @@ struct four_way_t{};
struct move_op
{
template <class SourceIt, class DestinationIt>
- void operator()(SourceIt source, DestinationIt dest)
+ BOOST_MOVE_FORCEINLINE void operator()(SourceIt source, DestinationIt dest)
{ *dest = ::boost::move(*source); }
template <class SourceIt, class DestinationIt>
- DestinationIt operator()(forward_t, SourceIt first, SourceIt last, DestinationIt dest_begin)
+ BOOST_MOVE_FORCEINLINE DestinationIt operator()(forward_t, SourceIt first, SourceIt last, DestinationIt dest_begin)
{ return ::boost::move(first, last, dest_begin); }
template <class SourceIt, class DestinationIt>
- DestinationIt operator()(backward_t, SourceIt first, SourceIt last, DestinationIt dest_last)
+ BOOST_MOVE_FORCEINLINE DestinationIt operator()(backward_t, SourceIt first, SourceIt last, DestinationIt dest_last)
{ return ::boost::move_backward(first, last, dest_last); }
template <class SourceIt, class DestinationIt1, class DestinationIt2>
- void operator()(three_way_t, SourceIt srcit, DestinationIt1 dest1it, DestinationIt2 dest2it)
+ BOOST_MOVE_FORCEINLINE void operator()(three_way_t, SourceIt srcit, DestinationIt1 dest1it, DestinationIt2 dest2it)
{
*dest2it = boost::move(*dest1it);
*dest1it = boost::move(*srcit);
@@ -64,7 +64,7 @@ struct move_op
}
template <class SourceIt, class DestinationIt1, class DestinationIt2, class DestinationIt3>
- void operator()(four_way_t, SourceIt srcit, DestinationIt1 dest1it, DestinationIt2 dest2it, DestinationIt3 dest3it)
+ BOOST_MOVE_FORCEINLINE void operator()(four_way_t, SourceIt srcit, DestinationIt1 dest1it, DestinationIt2 dest2it, DestinationIt3 dest3it)
{
*dest3it = boost::move(*dest2it);
*dest2it = boost::move(*dest1it);
@@ -75,19 +75,19 @@ struct move_op
struct swap_op
{
template <class SourceIt, class DestinationIt>
- void operator()(SourceIt source, DestinationIt dest)
+ BOOST_MOVE_FORCEINLINE void operator()(SourceIt source, DestinationIt dest)
{ boost::adl_move_swap(*dest, *source); }
template <class SourceIt, class DestinationIt>
- DestinationIt operator()(forward_t, SourceIt first, SourceIt last, DestinationIt dest_begin)
+ BOOST_MOVE_FORCEINLINE DestinationIt operator()(forward_t, SourceIt first, SourceIt last, DestinationIt dest_begin)
{ return boost::adl_move_swap_ranges(first, last, dest_begin); }
template <class SourceIt, class DestinationIt>
- DestinationIt operator()(backward_t, SourceIt first, SourceIt last, DestinationIt dest_begin)
+ BOOST_MOVE_FORCEINLINE DestinationIt operator()(backward_t, SourceIt first, SourceIt last, DestinationIt dest_begin)
{ return boost::adl_move_swap_ranges_backward(first, last, dest_begin); }
template <class SourceIt, class DestinationIt1, class DestinationIt2>
- void operator()(three_way_t, SourceIt srcit, DestinationIt1 dest1it, DestinationIt2 dest2it)
+ BOOST_MOVE_FORCEINLINE void operator()(three_way_t, SourceIt srcit, DestinationIt1 dest1it, DestinationIt2 dest2it)
{
typename ::boost::movelib::iterator_traits<SourceIt>::value_type tmp(boost::move(*dest2it));
*dest2it = boost::move(*dest1it);
@@ -105,7 +105,7 @@ struct swap_op
}
template <class SourceIt, class DestinationIt1, class DestinationIt2, class DestinationIt3>
- void operator()(four_way_t, SourceIt srcit, DestinationIt1 dest1it, DestinationIt2 dest2it, DestinationIt3 dest3it)
+ BOOST_MOVE_FORCEINLINE void operator()(four_way_t, SourceIt srcit, DestinationIt1 dest1it, DestinationIt2 dest2it, DestinationIt3 dest3it)
{
typename ::boost::movelib::iterator_traits<SourceIt>::value_type tmp(boost::move(*dest3it));
*dest3it = boost::move(*dest2it);
diff --git a/boost/move/algo/detail/insertion_sort.hpp b/boost/move/algo/detail/insertion_sort.hpp
index 15df35d9d6..3328f75748 100644
--- a/boost/move/algo/detail/insertion_sort.hpp
+++ b/boost/move/algo/detail/insertion_sort.hpp
@@ -31,6 +31,7 @@
#include <boost/move/detail/destruct_n.hpp>
#include <boost/move/algo/detail/basic_op.hpp>
#include <boost/move/detail/placement_new.hpp>
+#include <boost/move/detail/iterator_to_raw_pointer.hpp>
namespace boost { namespace movelib{
@@ -91,30 +92,30 @@ void insertion_sort(BirdirectionalIterator first, BirdirectionalIterator last, C
}
}
-template <class Compare, class BirdirectionalIterator>
+template <class Compare, class BirdirectionalIterator, class BirdirectionalRawIterator>
void insertion_sort_uninitialized_copy
(BirdirectionalIterator first1, BirdirectionalIterator const last1
- , typename iterator_traits<BirdirectionalIterator>::value_type* const first2
+ , BirdirectionalRawIterator const first2
, Compare comp)
{
typedef typename iterator_traits<BirdirectionalIterator>::value_type value_type;
if (first1 != last1){
- value_type* last2 = first2;
- ::new(last2, boost_move_new_t()) value_type(move(*first1));
- destruct_n<value_type> d(first2);
+ BirdirectionalRawIterator last2 = first2;
+ ::new((iterator_to_raw_pointer)(last2), boost_move_new_t()) value_type(move(*first1));
+ destruct_n<value_type, BirdirectionalRawIterator> d(first2);
d.incr();
for (++last2; ++first1 != last1; ++last2){
- value_type* j2 = last2;
- value_type* k2 = j2;
+ BirdirectionalRawIterator j2 = last2;
+ BirdirectionalRawIterator k2 = j2;
if (comp(*first1, *--k2)){
- ::new(j2, boost_move_new_t()) value_type(move(*k2));
+ ::new((iterator_to_raw_pointer)(j2), boost_move_new_t()) value_type(move(*k2));
d.incr();
for (--j2; k2 != first2 && comp(*first1, *--k2); --j2)
*j2 = move(*k2);
*j2 = move(*first1);
}
else{
- ::new(j2, boost_move_new_t()) value_type(move(*first1));
+ ::new((iterator_to_raw_pointer)(j2), boost_move_new_t()) value_type(move(*first1));
d.incr();
}
}
diff --git a/boost/move/algo/detail/merge.hpp b/boost/move/algo/detail/merge.hpp
index 988ffd35be..621dfa28af 100644
--- a/boost/move/algo/detail/merge.hpp
+++ b/boost/move/algo/detail/merge.hpp
@@ -16,6 +16,8 @@
#include <boost/move/algo/detail/basic_op.hpp>
#include <boost/move/detail/iterator_traits.hpp>
#include <boost/move/detail/destruct_n.hpp>
+#include <boost/move/algo/predicate.hpp>
+#include <boost/move/detail/iterator_to_raw_pointer.hpp>
#include <boost/assert.hpp>
namespace boost {
@@ -181,9 +183,6 @@ void op_merge_left( RandIt buf_first
//and all elements from the second half are less)
op(forward_t(), first1, last1, buf_first);
}
- else{
- buf_first = buf_first;
- }
}
// [buf_first, first1) -> buffer
@@ -312,13 +311,13 @@ void merge_bufferless_ONlogN_recursive
if (len1 > len2) {
len11 = len1 / 2;
first_cut += len11;
- second_cut = lower_bound(middle, last, *first_cut, comp);
+ second_cut = boost::movelib::lower_bound(middle, last, *first_cut, comp);
len22 = size_type(second_cut - middle);
}
else {
len22 = len2 / 2;
second_cut += len22;
- first_cut = upper_bound(first, middle, *second_cut, comp);
+ first_cut = boost::movelib::upper_bound(first, middle, *second_cut, comp);
len11 = size_type(first_cut - first);
}
BidirIt new_middle = rotate_gcd(first_cut, middle, second_cut);
@@ -359,7 +358,7 @@ void merge_bufferless_ON2(RandIt first, RandIt middle, RandIt last, Compare comp
if((middle - first) < (last - middle)){
while(first != middle){
RandIt const old_last1 = middle;
- middle = lower_bound(middle, last, *first, comp);
+ middle = boost::movelib::lower_bound(middle, last, *first, comp);
first = rotate_gcd(first, old_last1, middle);
if(middle == last){
break;
@@ -371,7 +370,7 @@ void merge_bufferless_ON2(RandIt first, RandIt middle, RandIt last, Compare comp
}
else{
while(middle != last){
- RandIt p = upper_bound(first, middle, last[-1], comp);
+ RandIt p = boost::movelib::upper_bound(first, middle, last[-1], comp);
last = rotate_gcd(p, middle, last);
middle = p;
if(middle == first){
@@ -396,65 +395,6 @@ void merge_bufferless(RandIt first, RandIt middle, RandIt last, Compare comp)
#endif //BOOST_ADAPTIVE_MERGE_NLOGN_MERGE
}
-template<class Comp>
-struct antistable
-{
- explicit antistable(Comp &comp)
- : m_comp(comp)
- {}
-
- template<class U, class V>
- bool operator()(const U &u, const V & v)
- { return !m_comp(v, u); }
-
- private:
- antistable & operator=(const antistable &);
- Comp &m_comp;
-};
-
-template <class Comp>
-class negate
-{
- public:
- negate()
- {}
-
- explicit negate(Comp comp)
- : m_comp(comp)
- {}
-
- template <class T1, class T2>
- bool operator()(const T1& l, const T2& r)
- {
- return !m_comp(l, r);
- }
-
- private:
- Comp m_comp;
-};
-
-
-template <class Comp>
-class inverse
-{
- public:
- inverse()
- {}
-
- explicit inverse(Comp comp)
- : m_comp(comp)
- {}
-
- template <class T1, class T2>
- bool operator()(const T1& l, const T2& r)
- {
- return m_comp(r, l);
- }
-
- private:
- Comp m_comp;
-};
-
// [r_first, r_last) are already in the right part of the destination range.
template <class Compare, class InputIterator, class InputOutIterator, class Op>
void op_merge_with_right_placed
@@ -557,12 +497,12 @@ void uninitialized_merge_with_right_placed
typedef typename iterator_traits<InputOutIterator>::value_type value_type;
InputOutIterator const original_r_first = r_first;
- destruct_n<value_type> d(&*dest_first);
+ destruct_n<value_type, InputOutIterator> d(dest_first);
while ( first != last && dest_first != original_r_first ) {
if (r_first == r_last) {
for(; dest_first != original_r_first; ++dest_first, ++first){
- ::new(&*dest_first) value_type(::boost::move(*first));
+ ::new((iterator_to_raw_pointer)(dest_first)) value_type(::boost::move(*first));
d.incr();
}
d.release();
@@ -572,12 +512,12 @@ void uninitialized_merge_with_right_placed
return;
}
else if (comp(*r_first, *first)) {
- ::new(&*dest_first) value_type(::boost::move(*r_first));
+ ::new((iterator_to_raw_pointer)(dest_first)) value_type(::boost::move(*r_first));
d.incr();
++r_first;
}
else {
- ::new(&*dest_first) value_type(::boost::move(*first));
+ ::new((iterator_to_raw_pointer)(dest_first)) value_type(::boost::move(*first));
d.incr();
++first;
}
diff --git a/boost/move/algo/detail/merge_sort.hpp b/boost/move/algo/detail/merge_sort.hpp
index 892639b05f..62d185acb6 100644
--- a/boost/move/algo/detail/merge_sort.hpp
+++ b/boost/move/algo/detail/merge_sort.hpp
@@ -79,9 +79,9 @@ void merge_sort_copy( RandIt first, RandIt last
}
}
-template<class RandIt, class Compare>
+template<class RandIt, class RandItRaw, class Compare>
void merge_sort_uninitialized_copy( RandIt first, RandIt last
- , typename iterator_traits<RandIt>::value_type* uninitialized
+ , RandItRaw uninitialized
, Compare comp)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
@@ -94,7 +94,7 @@ void merge_sort_uninitialized_copy( RandIt first, RandIt last
else{
size_type const half = count/2;
merge_sort_uninitialized_copy(first + half, last, uninitialized + half, comp);
- destruct_n<value_type> d(uninitialized+half);
+ destruct_n<value_type, RandItRaw> d(uninitialized+half);
d.incr(count-half);
merge_sort_copy(first, first + half, first + half, comp);
uninitialized_merge_with_right_placed
@@ -105,9 +105,9 @@ void merge_sort_uninitialized_copy( RandIt first, RandIt last
}
}
-template<class RandIt, class Compare>
+template<class RandIt, class RandItRaw, class Compare>
void merge_sort( RandIt first, RandIt last, Compare comp
- , typename iterator_traits<RandIt>::value_type* uninitialized)
+ , RandItRaw uninitialized)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
typedef typename iterator_traits<RandIt>::value_type value_type;
@@ -123,7 +123,7 @@ void merge_sort( RandIt first, RandIt last, Compare comp
RandIt const rest_it = first + rest;
merge_sort_uninitialized_copy(half_it, last, uninitialized, comp);
- destruct_n<value_type> d(uninitialized);
+ destruct_n<value_type, RandItRaw> d(uninitialized);
d.incr(rest);
merge_sort_copy(first, half_it, rest_it, comp);
merge_with_right_placed
diff --git a/boost/move/algo/move.hpp b/boost/move/algo/move.hpp
index d35f04a399..2390877a43 100644
--- a/boost/move/algo/move.hpp
+++ b/boost/move/algo/move.hpp
@@ -26,6 +26,7 @@
#include <boost/move/utility_core.hpp>
#include <boost/move/detail/iterator_traits.hpp>
+#include <boost/move/detail/iterator_to_raw_pointer.hpp>
#include <boost/detail/no_exceptions_support.hpp>
namespace boost {
@@ -126,7 +127,7 @@ F uninitialized_move(I f, I l, F r
}
BOOST_CATCH(...){
for (; back != r; ++back){
- back->~input_value_type();
+ boost::movelib::iterator_to_raw_pointer(back)->~input_value_type();
}
BOOST_RETHROW;
}
diff --git a/boost/move/algo/predicate.hpp b/boost/move/algo/predicate.hpp
new file mode 100644
index 0000000000..0287d66318
--- /dev/null
+++ b/boost/move/algo/predicate.hpp
@@ -0,0 +1,86 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_MOVE_ALGO_PREDICATE_HPP
+#define BOOST_MOVE_ALGO_PREDICATE_HPP
+
+#include <boost/move/algo/move.hpp>
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/move/algo/detail/basic_op.hpp>
+#include <boost/move/detail/iterator_traits.hpp>
+#include <boost/move/detail/destruct_n.hpp>
+#include <boost/assert.hpp>
+
+namespace boost {
+namespace movelib {
+
+template<class Comp>
+struct antistable
+{
+ explicit antistable(Comp &comp)
+ : m_comp(comp)
+ {}
+
+ template<class U, class V>
+ bool operator()(const U &u, const V & v)
+ { return !m_comp(v, u); }
+
+ private:
+ antistable & operator=(const antistable &);
+ Comp &m_comp;
+};
+
+template <class Comp>
+class negate
+{
+ public:
+ negate()
+ {}
+
+ explicit negate(Comp comp)
+ : m_comp(comp)
+ {}
+
+ template <class T1, class T2>
+ bool operator()(const T1& l, const T2& r)
+ {
+ return !m_comp(l, r);
+ }
+
+ private:
+ Comp m_comp;
+};
+
+
+template <class Comp>
+class inverse
+{
+ public:
+ inverse()
+ {}
+
+ explicit inverse(Comp comp)
+ : m_comp(comp)
+ {}
+
+ template <class T1, class T2>
+ bool operator()(const T1& l, const T2& r)
+ {
+ return m_comp(r, l);
+ }
+
+ private:
+ Comp m_comp;
+};
+
+} //namespace movelib {
+} //namespace boost {
+
+#endif //#define BOOST_MOVE_ALGO_PREDICATE_HPP
diff --git a/boost/move/algo/unique.hpp b/boost/move/algo/unique.hpp
new file mode 100644
index 0000000000..8022a654e2
--- /dev/null
+++ b/boost/move/algo/unique.hpp
@@ -0,0 +1,55 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_MOVE_ALGO_UNIQUE_HPP
+#define BOOST_MOVE_ALGO_UNIQUE_HPP
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/utility_core.hpp>
+
+namespace boost {
+namespace movelib {
+
+//! <b>Requires</b>: The comparison function shall be an equivalence relation. The type of *first shall satisfy
+//! the MoveAssignable requirements
+//!
+//! <b>Effects</b>: For a nonempty range, eliminates all but the first element from every consecutive group
+//! of equivalent elements referred to by the iterator i in the range [first + 1, last) for which the
+//! following conditions hold: pred(*(i - 1), *i) != false.
+//!
+//! <b>Returns</b>: The end of the resulting range.
+//!
+//! <b>Complexity</b>: For nonempty ranges, exactly (last - first) - 1 applications of the corresponding predicate.
+template<class ForwardIterator, class BinaryPredicate>
+ForwardIterator unique(ForwardIterator first, ForwardIterator last, BinaryPredicate pred)
+{
+ if (first != last) {
+ ForwardIterator next(first);
+ ++next;
+ for (; next != last; ++next, ++first) {
+ if (pred(*first, *next)) { //Find first equal element
+ while (++next != last)
+ if (!pred(*first, *next))
+ *++first = ::boost::move(*next);
+ break;
+ }
+ }
+ ++first;
+ }
+ return first;
+}
+
+} //namespace movelib {
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#define BOOST_MOVE_ALGO_UNIQUE_HPP
diff --git a/boost/move/detail/destruct_n.hpp b/boost/move/detail/destruct_n.hpp
index 06f1f589ed..9f60fc2773 100644
--- a/boost/move/detail/destruct_n.hpp
+++ b/boost/move/detail/destruct_n.hpp
@@ -27,11 +27,11 @@
namespace boost {
namespace movelib{
-template<class T>
+template<class T, class RandItUninit>
class destruct_n
{
public:
- explicit destruct_n(T *raw)
+ explicit destruct_n(RandItUninit raw)
: m_ptr(raw), m_size()
{}
@@ -48,7 +48,6 @@ class destruct_n
void release()
{
m_size = 0u;
- m_ptr = 0;
}
~destruct_n()
@@ -58,7 +57,7 @@ class destruct_n
}
}
private:
- T *m_ptr;
+ RandItUninit m_ptr;
std::size_t m_size;
};
diff --git a/boost/move/detail/fwd_macros.hpp b/boost/move/detail/fwd_macros.hpp
index 7132436783..a5df5f1be7 100644
--- a/boost/move/detail/fwd_macros.hpp
+++ b/boost/move/detail/fwd_macros.hpp
@@ -458,6 +458,31 @@ namespace move_detail {
#define BOOST_MOVE_CLASSDFLTQ8 BOOST_MOVE_CLASSDFLTQ7, class Q7 = void
#define BOOST_MOVE_CLASSDFLTQ9 BOOST_MOVE_CLASSDFLTQ8, class Q8 = void
+//BOOST_MOVE_LAST_TARGN
+#define BOOST_MOVE_LAST_TARG0 void
+#define BOOST_MOVE_LAST_TARG1 P0
+#define BOOST_MOVE_LAST_TARG2 P1
+#define BOOST_MOVE_LAST_TARG3 P2
+#define BOOST_MOVE_LAST_TARG4 P3
+#define BOOST_MOVE_LAST_TARG5 P4
+#define BOOST_MOVE_LAST_TARG6 P5
+#define BOOST_MOVE_LAST_TARG7 P6
+#define BOOST_MOVE_LAST_TARG8 P7
+#define BOOST_MOVE_LAST_TARG9 P8
+
+//BOOST_MOVE_LAST_TARGQN
+#define BOOST_MOVE_LAST_TARGQ0 void
+#define BOOST_MOVE_LAST_TARGQ1 Q0
+#define BOOST_MOVE_LAST_TARGQ2 Q1
+#define BOOST_MOVE_LAST_TARGQ3 Q2
+#define BOOST_MOVE_LAST_TARGQ4 Q3
+#define BOOST_MOVE_LAST_TARGQ5 Q4
+#define BOOST_MOVE_LAST_TARGQ6 Q5
+#define BOOST_MOVE_LAST_TARGQ7 Q6
+#define BOOST_MOVE_LAST_TARGQ8 Q7
+#define BOOST_MOVE_LAST_TARGQ9 Q8
+
+
//BOOST_MOVE_TARGN
#define BOOST_MOVE_TARG0
#define BOOST_MOVE_TARG1 P0
diff --git a/boost/move/detail/iterator_to_raw_pointer.hpp b/boost/move/detail/iterator_to_raw_pointer.hpp
new file mode 100644
index 0000000000..97ee3a6595
--- /dev/null
+++ b/boost/move/detail/iterator_to_raw_pointer.hpp
@@ -0,0 +1,59 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_MOVE_DETAIL_ITERATOR_TO_RAW_POINTER_HPP
+#define BOOST_MOVE_DETAIL_ITERATOR_TO_RAW_POINTER_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/iterator_traits.hpp>
+#include <boost/move/detail/to_raw_pointer.hpp>
+#include <boost/move/detail/pointer_element.hpp>
+
+namespace boost {
+namespace movelib {
+namespace detail {
+
+template <class T>
+inline T* iterator_to_pointer(T* i)
+{ return i; }
+
+template <class Iterator>
+inline typename boost::movelib::iterator_traits<Iterator>::pointer
+ iterator_to_pointer(const Iterator &i)
+{ return i.operator->(); }
+
+template <class Iterator>
+struct iterator_to_element_ptr
+{
+ typedef typename boost::movelib::iterator_traits<Iterator>::pointer pointer;
+ typedef typename boost::movelib::pointer_element<pointer>::type element_type;
+ typedef element_type* type;
+};
+
+} //namespace detail {
+
+template <class Iterator>
+inline typename boost::movelib::detail::iterator_to_element_ptr<Iterator>::type
+ iterator_to_raw_pointer(const Iterator &i)
+{
+ return ::boost::movelib::to_raw_pointer
+ ( ::boost::movelib::detail::iterator_to_pointer(i) );
+}
+
+} //namespace movelib {
+} //namespace boost {
+
+#endif //#ifndef BOOST_MOVE_DETAIL_ITERATOR_TO_RAW_POINTER_HPP
diff --git a/boost/intrusive/detail/pointer_element.hpp b/boost/move/detail/pointer_element.hpp
index dd26e3cf0b..ecdd6080ce 100644
--- a/boost/intrusive/detail/pointer_element.hpp
+++ b/boost/move/detail/pointer_element.hpp
@@ -1,15 +1,15 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2014-2014. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2014-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/intrusive for documentation.
+// See http://www.boost.org/libs/move for documentation.
//
//////////////////////////////////////////////////////////////////////////////
-#ifndef BOOST_INTRUSIVE_DETAIL_POINTER_ELEMENT_HPP
-#define BOOST_INTRUSIVE_DETAIL_POINTER_ELEMENT_HPP
+#ifndef BOOST_MOVE_DETAIL_POINTER_ELEMENT_HPP
+#define BOOST_MOVE_DETAIL_POINTER_ELEMENT_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
@@ -19,12 +19,12 @@
# pragma once
#endif
-#ifndef BOOST_INTRUSIVE_DETAIL_WORKAROUND_HPP
-#include <boost/intrusive/detail/workaround.hpp>
-#endif //BOOST_INTRUSIVE_DETAIL_WORKAROUND_HPP
+#ifndef BOOST_MOVE_DETAIL_WORKAROUND_HPP
+#include <boost/move/detail/workaround.hpp>
+#endif //BOOST_MOVE_DETAIL_WORKAROUND_HPP
namespace boost {
-namespace intrusive {
+namespace movelib {
namespace detail{
//////////////////////
@@ -147,7 +147,7 @@ struct pointer_element_impl
template<class Ptr>
struct pointer_element_impl<Ptr, false>
{
- typedef typename boost::intrusive::detail::first_param<Ptr>::type type;
+ typedef typename boost::movelib::detail::first_param<Ptr>::type type;
};
} //namespace detail{
@@ -155,14 +155,14 @@ struct pointer_element_impl<Ptr, false>
template <typename Ptr>
struct pointer_element
{
- typedef typename ::boost::intrusive::detail::pointer_element_impl<Ptr>::type type;
+ typedef typename ::boost::movelib::detail::pointer_element_impl<Ptr>::type type;
};
template <typename T>
struct pointer_element<T*>
{ typedef T type; };
-} //namespace container {
+} //namespace movelib {
} //namespace boost {
-#endif // defined(BOOST_INTRUSIVE_DETAIL_POINTER_ELEMENT_HPP)
+#endif // defined(BOOST_MOVE_DETAIL_POINTER_ELEMENT_HPP)
diff --git a/boost/move/detail/to_raw_pointer.hpp b/boost/move/detail/to_raw_pointer.hpp
new file mode 100644
index 0000000000..7e89beb4db
--- /dev/null
+++ b/boost/move/detail/to_raw_pointer.hpp
@@ -0,0 +1,45 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_MOVE_DETAIL_TO_RAW_POINTER_HPP
+#define BOOST_MOVE_DETAIL_TO_RAW_POINTER_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp>
+#include <boost/move/detail/pointer_element.hpp>
+
+namespace boost {
+namespace movelib {
+
+template <class T>
+BOOST_MOVE_FORCEINLINE T* to_raw_pointer(T* p)
+{ return p; }
+
+template <class Pointer>
+BOOST_MOVE_FORCEINLINE typename boost::movelib::pointer_element<Pointer>::type*
+to_raw_pointer(const Pointer &p)
+{ return ::boost::movelib::to_raw_pointer(p.operator->()); }
+
+} //namespace movelib
+} //namespace boost
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //BOOST_MOVE_DETAIL_TO_RAW_POINTER_HPP
diff --git a/boost/move/detail/unique_ptr_meta_utils.hpp b/boost/move/detail/unique_ptr_meta_utils.hpp
index ac270a8fc0..e11124d898 100644
--- a/boost/move/detail/unique_ptr_meta_utils.hpp
+++ b/boost/move/detail/unique_ptr_meta_utils.hpp
@@ -446,7 +446,7 @@ class is_convertible
#define BOOST_MOVE_TT_DECL
#endif
-#if defined(_MSC_EXTENSIONS) && !defined(__BORLAND__) && !defined(_WIN64) && !defined(_M_ARM) && !defined(UNDER_CE)
+#if defined(_MSC_EXTENSIONS) && !defined(__BORLAND__) && !defined(_WIN64) && !defined(_M_ARM) && !defined(_M_ARM64) && !defined(UNDER_CE)
#define BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS
#endif
diff --git a/boost/mpi/detail/antiques.hpp b/boost/mpi/detail/antiques.hpp
new file mode 100644
index 0000000000..6ece779777
--- /dev/null
+++ b/boost/mpi/detail/antiques.hpp
@@ -0,0 +1,29 @@
+// Copyright Alain Miniussi 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)
+
+// Authors: Alain Miniussi
+
+#ifndef BOOST_MPI_ANTIQUES_HPP
+#define BOOST_MPI_ANTIQUES_HPP
+
+#include <vector>
+
+// Support for some obsolette compilers
+
+namespace boost { namespace mpi {
+ namespace detail {
+ // Some old gnu compiler have no support for vector<>::data
+ // Use this in the mean time, the cumbersome syntax should
+ // serve as an incentive to get rid of this when those compilers
+ // are dropped.
+ template <typename T, typename A>
+ T* c_data(std::vector<T,A>& v) { return &(v[0]); }
+
+ template <typename T, typename A>
+ T const* c_data(std::vector<T,A> const& v) { return &(v[0]); }
+
+} } }
+
+#endif
diff --git a/boost/mpi/detail/mpi_datatype_primitive.hpp b/boost/mpi/detail/mpi_datatype_primitive.hpp
index c230055ab5..b2263fac4c 100644
--- a/boost/mpi/detail/mpi_datatype_primitive.hpp
+++ b/boost/mpi/detail/mpi_datatype_primitive.hpp
@@ -25,10 +25,10 @@ namespace std{
#include <boost/assert.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/serialization/array.hpp>
-#include <boost/serialization/detail/get_data.hpp>
#include <stdexcept>
#include <iostream>
#include <vector>
+#include <boost/mpi/detail/antiques.hpp>
namespace boost { namespace mpi { namespace detail {
@@ -80,18 +80,18 @@ public:
BOOST_MPI_CHECK_RESULT(MPI_Type_create_struct,
(
addresses.size(),
- boost::serialization::detail::get_data(lengths),
- boost::serialization::detail::get_data(addresses),
- boost::serialization::detail::get_data(types),
+ c_data(lengths),
+ c_data(addresses),
+ c_data(types),
&datatype_
));
#else
BOOST_MPI_CHECK_RESULT(MPI_Type_struct,
(
addresses.size(),
- boost::serialization::detail::get_data(lengths),
- boost::serialization::detail::get_data(addresses),
- boost::serialization::detail::get_data(types),
+ c_data(lengths),
+ c_data(addresses),
+ c_data(types),
&datatype_
));
#endif
diff --git a/boost/mpi/detail/packed_iprimitive.hpp b/boost/mpi/detail/packed_iprimitive.hpp
index 7080cbf53b..69d2c73a2b 100644
--- a/boost/mpi/detail/packed_iprimitive.hpp
+++ b/boost/mpi/detail/packed_iprimitive.hpp
@@ -16,8 +16,8 @@
#include <boost/mpi/exception.hpp>
#include <boost/assert.hpp>
#include <boost/serialization/array.hpp>
-#include <boost/serialization/detail/get_data.hpp>
#include <vector>
+#include <boost/mpi/detail/antiques.hpp>
#include <boost/mpi/allocator.hpp>
namespace boost { namespace mpi {
@@ -104,7 +104,7 @@ private:
void load_impl(void * p, MPI_Datatype t, int l)
{
BOOST_MPI_CHECK_RESULT(MPI_Unpack,
- (const_cast<char*>(boost::serialization::detail::get_data(buffer_)), buffer_.size(), &position, p, l, t, comm));
+ (const_cast<char*>(detail::c_data(buffer_)), buffer_.size(), &position, p, l, t, comm));
}
buffer_type & buffer_;
diff --git a/boost/mpi/detail/packed_oprimitive.hpp b/boost/mpi/detail/packed_oprimitive.hpp
index 5b6b3b2708..1cb4ba0c26 100644
--- a/boost/mpi/detail/packed_oprimitive.hpp
+++ b/boost/mpi/detail/packed_oprimitive.hpp
@@ -15,7 +15,7 @@
#include <boost/mpi/datatype.hpp>
#include <boost/mpi/exception.hpp>
-#include <boost/serialization/detail/get_data.hpp>
+#include <boost/mpi/detail/antiques.hpp>
#include <boost/serialization/array.hpp>
#include <boost/assert.hpp>
#include <vector>
@@ -98,7 +98,10 @@ private:
// pack the data into the buffer
BOOST_MPI_CHECK_RESULT(MPI_Pack,
- (const_cast<void*>(p), l, t, boost::serialization::detail::get_data(buffer_), buffer_.size(), &position, comm));
+ (const_cast<void*>(p),l,t,
+ detail::c_data(buffer_),
+ buffer_.size(),
+ &position,comm));
// reduce the buffer size if needed
BOOST_ASSERT(std::size_t(position) <= buffer_.size());
if (std::size_t(position) < buffer_.size())
diff --git a/boost/mpi/python/serialize.hpp b/boost/mpi/python/serialize.hpp
index 5f9136bd5a..8933b3405f 100644
--- a/boost/mpi/python/serialize.hpp
+++ b/boost/mpi/python/serialize.hpp
@@ -36,6 +36,7 @@
#include <boost/serialization/split_free.hpp>
#include <boost/serialization/array.hpp>
+#include <boost/serialization/array_wrapper.hpp>
#include <boost/assert.hpp>
diff --git a/boost/multiprecision/cpp_bin_float.hpp b/boost/multiprecision/cpp_bin_float.hpp
index f3e593a142..c8cf06bc50 100644
--- a/boost/multiprecision/cpp_bin_float.hpp
+++ b/boost/multiprecision/cpp_bin_float.hpp
@@ -103,6 +103,10 @@ public:
(number_category<Float>::value == number_kind_floating_point)
&& (std::numeric_limits<Float>::digits <= (int)bit_count)
&& (std::numeric_limits<Float>::radix == 2)
+ && (std::numeric_limits<Float>::is_specialized)
+#ifdef BOOST_HAS_FLOAT128
+ && !boost::is_same<Float, __float128>::value
+#endif
>::type const* = 0)
: m_data(), m_exponent(0), m_sign(false)
{
@@ -113,14 +117,39 @@ public:
explicit cpp_bin_float(const Float& f,
typename boost::enable_if_c<
(number_category<Float>::value == number_kind_floating_point)
- && (std::numeric_limits<Float>::digits > (int)bit_count)
- && (std::numeric_limits<Float>::radix == 2)
+ && (std::numeric_limits<Float>::digits > (int)bit_count)
+ && (std::numeric_limits<Float>::radix == 2)
+ && (std::numeric_limits<Float>::is_specialized)
+#ifdef BOOST_HAS_FLOAT128
+ && !boost::is_same<Float, __float128>::value
+#endif
+>::type const* = 0)
+ : m_data(), m_exponent(0), m_sign(false)
+ {
+ this->assign_float(f);
+ }
+#ifdef BOOST_HAS_FLOAT128
+ template <class Float>
+ cpp_bin_float(const Float& f,
+ typename boost::enable_if_c<
+ boost::is_same<Float, __float128>::value
+ && ((int)bit_count >= 113)
>::type const* = 0)
: m_data(), m_exponent(0), m_sign(false)
{
this->assign_float(f);
}
-
+ template <class Float>
+ explicit cpp_bin_float(const Float& f,
+ typename boost::enable_if_c<
+ boost::is_same<Float, __float128>::value
+ && ((int)bit_count < 113)
+ >::type const* = 0)
+ : m_data(), m_exponent(0), m_sign(false)
+ {
+ this->assign_float(f);
+ }
+#endif
cpp_bin_float& operator=(const cpp_bin_float &o) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<rep_type&>() = std::declval<const rep_type&>()))
{
m_data = o.m_data;
@@ -157,22 +186,31 @@ public:
}
return *this;
}
-
+#ifdef BOOST_HAS_FLOAT128
+ template <class Float>
+ typename boost::enable_if_c<
+ (number_category<Float>::value == number_kind_floating_point)
+ //&& (std::numeric_limits<Float>::digits <= (int)bit_count)
+ && ((std::numeric_limits<Float>::radix == 2) || (boost::is_same<Float, __float128>::value)), cpp_bin_float&>::type
+ operator=(const Float& f)
+#else
template <class Float>
typename boost::enable_if_c<
(number_category<Float>::value == number_kind_floating_point)
//&& (std::numeric_limits<Float>::digits <= (int)bit_count)
- && (std::numeric_limits<Float>::radix == 2), cpp_bin_float&>::type operator=(const Float& f)
+ && (std::numeric_limits<Float>::radix == 2), cpp_bin_float&>::type
+ operator=(const Float& f)
+#endif
{
return assign_float(f);
}
#ifdef BOOST_HAS_FLOAT128
- cpp_bin_float& operator=(__float128 f)
+ template <class Float>
+ typename boost::enable_if_c<boost::is_same<Float, __float128>::value, cpp_bin_float& >::type assign_float(Float f)
{
using default_ops::eval_add;
typedef typename boost::multiprecision::detail::canonical<int, cpp_bin_float>::type bf_int_type;
-
if(f == 0)
{
m_data = limb_type(0);
@@ -224,9 +262,13 @@ public:
return *this;
}
#endif
-
+#ifdef BOOST_HAS_FLOAT128
+ template <class Float>
+ typename boost::enable_if_c<is_floating_point<Float>::value && !is_same<Float, __float128>::value, cpp_bin_float&>::type assign_float(Float f)
+#else
template <class Float>
typename boost::enable_if_c<is_floating_point<Float>::value, cpp_bin_float&>::type assign_float(Float f)
+#endif
{
BOOST_MATH_STD_USING
using default_ops::eval_add;
diff --git a/boost/multiprecision/cpp_bin_float/transcendental.hpp b/boost/multiprecision/cpp_bin_float/transcendental.hpp
index 066bc458e4..604ed85159 100644
--- a/boost/multiprecision/cpp_bin_float/transcendental.hpp
+++ b/boost/multiprecision/cpp_bin_float/transcendental.hpp
@@ -110,10 +110,19 @@ void eval_exp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>
// rounds up, in that situation t ends up negative at this point which breaks our invariants below:
t = limb_type(0);
}
- BOOST_ASSERT(t.compare(default_ops::get_constant_ln2<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> >()) < 0);
Exponent k, nn;
eval_convert_to(&nn, n);
+
+ if (nn == (std::numeric_limits<Exponent>::max)())
+ {
+ // The result will necessarily oveflow:
+ res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
+ return;
+ }
+
+ BOOST_ASSERT(t.compare(default_ops::get_constant_ln2<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> >()) < 0);
+
k = nn ? Exponent(1) << (msb(nn) / 2) : 0;
eval_ldexp(t, t, -k);
diff --git a/boost/multiprecision/cpp_dec_float.hpp b/boost/multiprecision/cpp_dec_float.hpp
index f9e6a22189..6e1509289d 100644
--- a/boost/multiprecision/cpp_dec_float.hpp
+++ b/boost/multiprecision/cpp_dec_float.hpp
@@ -255,7 +255,11 @@ public:
}
template <class F>
- cpp_dec_float(const F val, typename enable_if<is_floating_point<F> >::type* = 0) :
+ cpp_dec_float(const F val, typename enable_if_c<is_floating_point<F>::value
+#ifdef BOOST_HAS_FLOAT128
+ && !boost::is_same<F, __float128>::value
+#endif
+ >::type* = 0) :
data(),
exp (static_cast<ExponentType>(0)),
neg (false),
@@ -2892,7 +2896,7 @@ template <unsigned Digits10, class ExponentType, class Allocator, class ArgType>
inline void eval_scalbn(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& val, ArgType e_)
{
using default_ops::eval_multiply;
- const ExponentType e = e_;
+ const ExponentType e = static_cast<ExponentType>(e_);
cpp_dec_float<Digits10, ExponentType, Allocator> t(1.0, e);
eval_multiply(result, val, t);
}
diff --git a/boost/multiprecision/cpp_int/multiply.hpp b/boost/multiprecision/cpp_int/multiply.hpp
index afe1db7a9f..151b2294c7 100644
--- a/boost/multiprecision/cpp_int/multiply.hpp
+++ b/boost/multiprecision/cpp_int/multiply.hpp
@@ -64,10 +64,10 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit
template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
inline void resize_for_carry(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& /*result*/, unsigned /*required*/){}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline void resize_for_carry(cpp_int_backend<MinBits1, MaxBits1, SignType1, checked, void>& result, unsigned required)
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, class Allocator1>
+inline void resize_for_carry(cpp_int_backend<MinBits1, MaxBits1, SignType1, checked, Allocator1>& result, unsigned required)
{
- if(result.size() != required)
+ if(result.size() < required)
result.resize(required, required);
}
@@ -136,7 +136,8 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit
for(unsigned i = 0; i < as; ++i)
{
unsigned inner_limit = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::variable ? bs : (std::min)(result.size() - i, bs);
- for(unsigned j = 0; j < inner_limit; ++j)
+ unsigned j;
+ for(j = 0; j < inner_limit; ++j)
{
BOOST_ASSERT(i+j < result.size());
#if (!defined(__GLIBCXX__) && !defined(__GLIBCPP__)) || !BOOST_WORKAROUND(BOOST_GCC_VERSION, <= 50100)
@@ -156,9 +157,16 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit
carry >>= cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
BOOST_ASSERT(carry <= (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value));
}
- resize_for_carry(result, as + bs); // May throw if checking is enabled
- if(i + bs < result.size())
- pr[i + bs] = static_cast<limb_type>(carry);
+ if(carry)
+ {
+ resize_for_carry(result, i + j + 1); // May throw if checking is enabled
+ if(i + j < result.size())
+#ifdef __MSVC_RUNTIME_CHECKS
+ pr[i + j] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
+#else
+ pr[i + j] = static_cast<limb_type>(carry);
+#endif
+ }
carry = 0;
}
result.normalize();
diff --git a/boost/multiprecision/detail/bitscan.hpp b/boost/multiprecision/detail/bitscan.hpp
index 21e8b8a3a9..c12606551f 100644
--- a/boost/multiprecision/detail/bitscan.hpp
+++ b/boost/multiprecision/detail/bitscan.hpp
@@ -143,9 +143,12 @@ BOOST_FORCEINLINE unsigned find_msb(boost::ulong_long_type mask, mpl::int_<3> co
return sizeof(boost::ulong_long_type) * CHAR_BIT - 1 - __builtin_clzll(mask);
}
#ifdef BOOST_HAS_INT128
-BOOST_FORCEINLINE unsigned find_msb(unsigned __int128 mask, mpl::int_<0> const&)
+
+__extension__ typedef unsigned __int128 uint128_type;
+
+BOOST_FORCEINLINE unsigned find_msb(uint128_type mask, mpl::int_<0> const&)
{
- union { unsigned __int128 v; boost::uint64_t sv[2]; } val;
+ union { uint128_type v; boost::uint64_t sv[2]; } val;
val.v = mask;
#ifdef BOOST_LITTLE_ENDIAN
if(val.sv[1])
@@ -157,9 +160,9 @@ BOOST_FORCEINLINE unsigned find_msb(unsigned __int128 mask, mpl::int_<0> const&)
return find_msb(val.sv[1], mpl::int_<3>());
#endif
}
-BOOST_FORCEINLINE unsigned find_lsb(unsigned __int128 mask, mpl::int_<0> const&)
+BOOST_FORCEINLINE unsigned find_lsb(uint128_type mask, mpl::int_<0> const&)
{
- union { unsigned __int128 v; boost::uint64_t sv[2]; } val;
+ union { uint128_type v; boost::uint64_t sv[2]; } val;
val.v = mask;
#ifdef BOOST_LITTLE_ENDIAN
if(val.sv[0] == 0)
diff --git a/boost/multiprecision/detail/default_ops.hpp b/boost/multiprecision/detail/default_ops.hpp
index 334db06a64..bfdb8bd368 100644
--- a/boost/multiprecision/detail/default_ops.hpp
+++ b/boost/multiprecision/detail/default_ops.hpp
@@ -1479,7 +1479,7 @@ inline typename B::exponent_type eval_ilogb(const B& val)
{
case FP_NAN:
#ifdef FP_ILOGBNAN
- return FP_ILOGBNAN;
+ return FP_ILOGBNAN > 0 ? (std::numeric_limits<typename B::exponent_type>::max)() : (std::numeric_limits<typename B::exponent_type>::min)();
#else
return (std::numeric_limits<typename B::exponent_type>::max)();
#endif
@@ -3201,10 +3201,21 @@ inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multi
return BOOST_MP_MOVE(boost::math::sinhc_pi(x));
}
+using boost::multiprecision::gcd;
+using boost::multiprecision::lcm;
+
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
} // namespace math
+
+namespace integer {
+
+using boost::multiprecision::gcd;
+using boost::multiprecision::lcm;
+
+}
+
} // namespace boost
//
diff --git a/boost/multiprecision/detail/functions/constants.hpp b/boost/multiprecision/detail/functions/constants.hpp
index e0a2ff5fcf..48b4a5c29a 100644
--- a/boost/multiprecision/detail/functions/constants.hpp
+++ b/boost/multiprecision/detail/functions/constants.hpp
@@ -295,3 +295,20 @@ const T& get_constant_pi()
return result;
}
+template <class T>
+const T& get_constant_one_over_epsilon()
+{
+ static const bool is_init = false;
+ static T result;
+ if (is_init == false)
+ {
+ typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
+ result = static_cast<ui_type>(1u);
+ eval_divide(result, std::numeric_limits<number<T> >::epsilon().backend());
+ }
+
+ constant_initializer<T, &get_constant_one_over_epsilon<T> >::do_nothing();
+
+ return result;
+}
+
diff --git a/boost/multiprecision/detail/functions/pow.hpp b/boost/multiprecision/detail/functions/pow.hpp
index 460658e034..179e37f400 100644
--- a/boost/multiprecision/detail/functions/pow.hpp
+++ b/boost/multiprecision/detail/functions/pow.hpp
@@ -303,6 +303,16 @@ void eval_exp(T& result, const T& x)
exp_type n;
eval_convert_to(&n, result);
+ if (n == (std::numeric_limits<exp_type>::max)())
+ {
+ // Exponent is too large to fit in our exponent type:
+ if (isneg)
+ result = ui_type(0);
+ else
+ result = std::numeric_limits<number<T> >::has_infinity ? std::numeric_limits<number<T> >::infinity().backend() : (std::numeric_limits<number<T> >::max)().backend();
+ return;
+ }
+
// The scaling is 2^11 = 2048.
const si_type p2 = static_cast<si_type>(si_type(1) << 11);
diff --git a/boost/multiprecision/detail/functions/trig.hpp b/boost/multiprecision/detail/functions/trig.hpp
index 319b708b0c..c001f955c9 100644
--- a/boost/multiprecision/detail/functions/trig.hpp
+++ b/boost/multiprecision/detail/functions/trig.hpp
@@ -128,7 +128,13 @@ void eval_sin(T& result, const T& x)
eval_fmod(t, n_pi, t);
const bool b_n_pi_is_even = eval_get_sign(t) == 0;
eval_multiply(n_pi, get_constant_pi<T>());
- eval_subtract(xx, n_pi);
+ if (n_pi.compare(get_constant_one_over_epsilon<T>()) > 0)
+ {
+ result = ui_type(0);
+ return;
+ }
+ else
+ eval_subtract(xx, n_pi);
BOOST_MATH_INSTRUMENT_CODE(xx.str(0, std::ios_base::scientific));
BOOST_MATH_INSTRUMENT_CODE(n_pi.str(0, std::ios_base::scientific));
@@ -276,7 +282,20 @@ void eval_cos(T& result, const T& x)
BOOST_MATH_INSTRUMENT_CODE(n_pi.str(0, std::ios_base::scientific));
eval_multiply(t, n_pi, get_constant_pi<T>());
BOOST_MATH_INSTRUMENT_CODE(t.str(0, std::ios_base::scientific));
- eval_subtract(xx, t);
+ //
+ // If t is so large that all digits cancel the result of this subtraction
+ // is completely meaningless, just assume the result is zero for now...
+ //
+ // TODO We should of course do much better, see:
+ // "ARGUMENT REDUCTION FOR HUGE ARGUMENTS" K C Ng 1992
+ //
+ if (n_pi.compare(get_constant_one_over_epsilon<T>()) > 0)
+ {
+ result = ui_type(1);
+ return;
+ }
+ else
+ eval_subtract(xx, t);
BOOST_MATH_INSTRUMENT_CODE(xx.str(0, std::ios_base::scientific));
// Adjust signs if the multiple of pi is not even.
diff --git a/boost/multiprecision/detail/number_base.hpp b/boost/multiprecision/detail/number_base.hpp
index 9b10dd82d7..ca065bb569 100644
--- a/boost/multiprecision/detail/number_base.hpp
+++ b/boost/multiprecision/detail/number_base.hpp
@@ -38,8 +38,9 @@
//
// Thread local storage:
+// Note fails on Mingw, see https://sourceforge.net/p/mingw-w64/bugs/527/
//
-#if !defined(BOOST_NO_CXX11_THREAD_LOCAL) && !defined(BOOST_INTEL)
+#if !defined(BOOST_NO_CXX11_THREAD_LOCAL) && !defined(BOOST_INTEL) && !defined(__MINGW32__)
# define BOOST_MP_THREAD_LOCAL thread_local
#else
# define BOOST_MP_THREAD_LOCAL
@@ -364,13 +365,22 @@ struct unmentionable
typedef unmentionable* (unmentionable::*unmentionable_type)();
-template <class T>
-struct expression_storage
+template <class T, bool b>
+struct expression_storage_base
{
typedef const T& type;
};
template <class T>
+struct expression_storage_base<T, true>
+{
+ typedef T type;
+};
+
+template <class T>
+struct expression_storage : public expression_storage_base<T, boost::is_arithmetic<T>::value> {};
+
+template <class T>
struct expression_storage<T*>
{
typedef T* type;
@@ -988,6 +998,19 @@ template <class Backend, expression_template_option ExpressionTemplates>
struct number_category<number<Backend, ExpressionTemplates> > : public number_category<Backend>{};
template <class tag, class A1, class A2, class A3, class A4>
struct number_category<detail::expression<tag, A1, A2, A3, A4> > : public number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>{};
+//
+// Specializations for types which do not always have numberic_limits specializations:
+//
+#ifdef BOOST_HAS_INT128
+template <>
+struct number_category<__int128> : public mpl::int_<number_kind_integer> {};
+template <>
+struct number_category<unsigned __int128> : public mpl::int_<number_kind_integer> {};
+#endif
+#ifdef BOOST_HAS_FLOAT128
+template <>
+struct number_category<__float128> : public mpl::int_<number_kind_floating_point> {};
+#endif
template <class T>
struct component_type;
diff --git a/boost/multiprecision/float128.hpp b/boost/multiprecision/float128.hpp
index 8de3af6519..a729523881 100644
--- a/boost/multiprecision/float128.hpp
+++ b/boost/multiprecision/float128.hpp
@@ -119,8 +119,10 @@ using backends::float128_backend;
template<>
struct number_category<backends::float128_backend> : public mpl::int_<number_kind_floating_point> {};
+#if defined(BOOST_MP_USE_QUAD)
template<>
struct number_category<float128_type> : public mpl::int_<number_kind_floating_point> {};
+#endif
typedef number<float128_backend, et_off> float128;
diff --git a/boost/multiprecision/gmp.hpp b/boost/multiprecision/gmp.hpp
index 266aff2285..6fd6204c4c 100644
--- a/boost/multiprecision/gmp.hpp
+++ b/boost/multiprecision/gmp.hpp
@@ -865,7 +865,7 @@ inline void eval_convert_to(long* result, const gmp_float<digits10>& val) BOOST_
{
if(0 == mpf_fits_slong_p(val.data()))
{
- *result = (std::numeric_limits<unsigned long>::max)();
+ *result = (std::numeric_limits<long>::max)();
*result *= mpf_sgn(val.data());
}
else
diff --git a/boost/multiprecision/number.hpp b/boost/multiprecision/number.hpp
index c3819dc561..dc61d696f2 100644
--- a/boost/multiprecision/number.hpp
+++ b/boost/multiprecision/number.hpp
@@ -48,6 +48,9 @@ public:
(boost::is_arithmetic<V>::value || is_same<std::string, V>::value || is_convertible<V, const char*>::value)
&& !is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value
&& !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value
+#ifdef BOOST_HAS_FLOAT128
+ && !boost::is_same<V, __float128>::value
+#endif
>::type* = 0)
{
m_backend = canonical_value(v);
diff --git a/boost/multiprecision/traits/is_backend.hpp b/boost/multiprecision/traits/is_backend.hpp
index 9b23c86665..2a26b19df0 100644
--- a/boost/multiprecision/traits/is_backend.hpp
+++ b/boost/multiprecision/traits/is_backend.hpp
@@ -13,9 +13,9 @@
namespace boost{ namespace multiprecision{ namespace detail{
- BOOST_MPL_HAS_XXX_TRAIT_DEF(signed_types);
- BOOST_MPL_HAS_XXX_TRAIT_DEF(unsigned_types);
- BOOST_MPL_HAS_XXX_TRAIT_DEF(float_types);
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(signed_types)
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(unsigned_types)
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(float_types)
template <class T>
struct is_backend
diff --git a/boost/multiprecision/traits/is_byte_container.hpp b/boost/multiprecision/traits/is_byte_container.hpp
index 1efda2930e..d97428f0f2 100644
--- a/boost/multiprecision/traits/is_byte_container.hpp
+++ b/boost/multiprecision/traits/is_byte_container.hpp
@@ -11,8 +11,8 @@
namespace boost{ namespace multiprecision{ namespace detail{
- BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_member_value_type, value_type, false);
- BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_member_const_iterator, const_iterator, false);
+ BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_member_value_type, value_type, false)
+ BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_member_const_iterator, const_iterator, false)
template <class C, bool b>
struct is_byte_container_imp
diff --git a/boost/next_prior.hpp b/boost/next_prior.hpp
index 7854ec436a..bad46ed654 100644
--- a/boost/next_prior.hpp
+++ b/boost/next_prior.hpp
@@ -1,8 +1,11 @@
// Boost next_prior.hpp header file ---------------------------------------//
-// (C) Copyright Dave Abrahams and Daniel Walker 1999-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)
+// (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.
@@ -13,17 +16,14 @@
#define BOOST_NEXT_PRIOR_HPP_INCLUDED
#include <iterator>
-#if defined(_MSC_VER) && _MSC_VER <= 1310
-#include <boost/mpl/and.hpp>
-#include <boost/type_traits/is_integral.hpp>
-#endif
-#include <boost/type_traits/is_unsigned.hpp>
-#include <boost/type_traits/integral_promotion.hpp>
-#include <boost/type_traits/make_signed.hpp>
+#include <boost/config.hpp>
+#include <boost/core/enable_if.hpp>
#include <boost/type_traits/has_plus.hpp>
#include <boost/type_traits/has_plus_assign.hpp>
#include <boost/type_traits/has_minus.hpp>
#include <boost/type_traits/has_minus_assign.hpp>
+#include <boost/iterator/advance.hpp>
+#include <boost/iterator/reverse_iterator.hpp>
namespace boost {
@@ -39,18 +39,36 @@ namespace boost {
namespace next_prior_detail {
-template< typename T, typename Distance, bool HasPlus = has_plus< T, Distance >::value >
-struct next_impl2
+// The trait attempts to detect if the T type is an iterator. 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<T>::iterator_category presence instead as it is
+// required to be only present for iterators.
+template< typename T, typename Void = void >
+struct is_iterator
{
- static T call(T x, Distance n)
- {
- std::advance(x, n);
- return x;
- }
+ static BOOST_CONSTEXPR_OR_CONST bool value = false;
+};
+
+template< typename T >
+struct is_iterator< T, typename enable_if_has_type< typename T::iterator_category >::type >
+{
+ static BOOST_CONSTEXPR_OR_CONST bool value = true;
};
+template< typename T >
+struct is_iterator< T*, void >
+{
+ static BOOST_CONSTEXPR_OR_CONST bool value = true;
+};
+
+
+template< typename T, typename Distance, bool HasPlus = has_plus< T, Distance >::value >
+struct next_plus_impl;
+
template< typename T, typename Distance >
-struct next_impl2< T, Distance, true >
+struct next_plus_impl< T, Distance, true >
{
static T call(T x, Distance n)
{
@@ -58,15 +76,14 @@ struct next_impl2< T, Distance, true >
}
};
-
template< typename T, typename Distance, bool HasPlusAssign = has_plus_assign< T, Distance >::value >
-struct next_impl1 :
- public next_impl2< T, Distance >
+struct next_plus_assign_impl :
+ public next_plus_impl< T, Distance >
{
};
template< typename T, typename Distance >
-struct next_impl1< T, Distance, true >
+struct next_plus_assign_impl< T, Distance, true >
{
static T call(T x, Distance n)
{
@@ -75,47 +92,28 @@ struct next_impl1< T, Distance, true >
}
};
-
-template<
- typename T,
- typename Distance,
- typename PromotedDistance = typename integral_promotion< Distance >::type,
-#if !defined(_MSC_VER) || _MSC_VER > 1310
- bool IsUInt = is_unsigned< PromotedDistance >::value
-#else
- // MSVC 7.1 has problems with applying is_unsigned to non-integral types
- bool IsUInt = mpl::and_< is_integral< PromotedDistance >, is_unsigned< PromotedDistance > >::value
-#endif
->
-struct prior_impl3
+template< typename T, typename Distance, bool IsIterator = is_iterator< T >::value >
+struct next_advance_impl :
+ public next_plus_assign_impl< T, Distance >
{
- static T call(T x, Distance n)
- {
- std::advance(x, -n);
- return x;
- }
};
-template< typename T, typename Distance, typename PromotedDistance >
-struct prior_impl3< T, Distance, PromotedDistance, true >
+template< typename T, typename Distance >
+struct next_advance_impl< T, Distance, true >
{
static T call(T x, Distance n)
{
- typedef typename make_signed< PromotedDistance >::type signed_distance;
- std::advance(x, -static_cast< signed_distance >(static_cast< PromotedDistance >(n)));
+ boost::iterators::advance(x, n);
return x;
}
};
template< typename T, typename Distance, bool HasMinus = has_minus< T, Distance >::value >
-struct prior_impl2 :
- public prior_impl3< T, Distance >
-{
-};
+struct prior_minus_impl;
template< typename T, typename Distance >
-struct prior_impl2< T, Distance, true >
+struct prior_minus_impl< T, Distance, true >
{
static T call(T x, Distance n)
{
@@ -123,15 +121,14 @@ struct prior_impl2< T, Distance, true >
}
};
-
template< typename T, typename Distance, bool HasMinusAssign = has_minus_assign< T, Distance >::value >
-struct prior_impl1 :
- public prior_impl2< T, Distance >
+struct prior_minus_assign_impl :
+ public prior_minus_impl< T, Distance >
{
};
template< typename T, typename Distance >
-struct prior_impl1< T, Distance, true >
+struct prior_minus_assign_impl< T, Distance, true >
{
static T call(T x, Distance n)
{
@@ -140,6 +137,24 @@ struct prior_impl1< T, Distance, true >
}
};
+template< typename T, typename Distance, bool IsIterator = 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 <class T>
@@ -148,7 +163,7 @@ inline T next(T x) { return ++x; }
template <class T, class Distance>
inline T next(T x, Distance n)
{
- return next_prior_detail::next_impl1< T, Distance >::call(x, n);
+ return next_prior_detail::next_advance_impl< T, Distance >::call(x, n);
}
template <class T>
@@ -157,7 +172,7 @@ inline T prior(T x) { return --x; }
template <class T, class Distance>
inline T prior(T x, Distance n)
{
- return next_prior_detail::prior_impl1< T, Distance >::call(x, n);
+ return next_prior_detail::prior_advance_impl< T, Distance >::call(x, n);
}
} // namespace boost
diff --git a/boost/numeric/interval.hpp b/boost/numeric/interval.hpp
index e6f976df03..1f75543072 100644
--- a/boost/numeric/interval.hpp
+++ b/boost/numeric/interval.hpp
@@ -1,7 +1,7 @@
/* Boost interval.hpp header file
*
* Copyright 2000 Jens Maurer
- * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/arith.hpp b/boost/numeric/interval/arith.hpp
index c0320c45ef..0d598be7d0 100644
--- a/boost/numeric/interval/arith.hpp
+++ b/boost/numeric/interval/arith.hpp
@@ -1,7 +1,7 @@
/* Boost interval/arith.hpp template implementation file
*
* Copyright 2000 Jens Maurer
- * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/arith2.hpp b/boost/numeric/interval/arith2.hpp
index 5501929e4b..b0aba7c04c 100644
--- a/boost/numeric/interval/arith2.hpp
+++ b/boost/numeric/interval/arith2.hpp
@@ -4,7 +4,7 @@
* functions: fmod, sqrt, square, pov, inverse and
* a multi-interval division.
*
- * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/checking.hpp b/boost/numeric/interval/checking.hpp
index 2db486a0be..f40ba65a55 100644
--- a/boost/numeric/interval/checking.hpp
+++ b/boost/numeric/interval/checking.hpp
@@ -1,6 +1,6 @@
/* Boost interval/checking.hpp template implementation file
*
- * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/compare.hpp b/boost/numeric/interval/compare.hpp
index f21753e711..0b4b751af1 100644
--- a/boost/numeric/interval/compare.hpp
+++ b/boost/numeric/interval/compare.hpp
@@ -1,6 +1,6 @@
/* Boost interval/compare.hpp template implementation file
*
- * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/compare/explicit.hpp b/boost/numeric/interval/compare/explicit.hpp
index 8c68be8916..f66dc641ed 100644
--- a/boost/numeric/interval/compare/explicit.hpp
+++ b/boost/numeric/interval/compare/explicit.hpp
@@ -1,7 +1,7 @@
/* Boost interval/compare/explicit.hpp template implementation file
*
* Copyright 2000 Jens Maurer
- * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/constants.hpp b/boost/numeric/interval/constants.hpp
index a3a42efece..6a228343ec 100644
--- a/boost/numeric/interval/constants.hpp
+++ b/boost/numeric/interval/constants.hpp
@@ -1,6 +1,6 @@
/* Boost interval/constants.hpp template implementation file
*
- * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/detail/alpha_rounding_control.hpp b/boost/numeric/interval/detail/alpha_rounding_control.hpp
index d9a6079e1b..25b6ff617f 100644
--- a/boost/numeric/interval/detail/alpha_rounding_control.hpp
+++ b/boost/numeric/interval/detail/alpha_rounding_control.hpp
@@ -1,6 +1,6 @@
/* Boost interval/detail/alpha_rounding_control.hpp file
*
- * Copyright 2005 Felix Höfling, Guillaume Melquiond
+ * Copyright 2005 Felix Höfling, Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/detail/bcc_rounding_control.hpp b/boost/numeric/interval/detail/bcc_rounding_control.hpp
index e3aaf046c5..c55d0823b2 100644
--- a/boost/numeric/interval/detail/bcc_rounding_control.hpp
+++ b/boost/numeric/interval/detail/bcc_rounding_control.hpp
@@ -1,7 +1,7 @@
/* Boost interval/detail/bcc_rounding_control.hpp file
*
* Copyright 2000 Jens Maurer
- * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/detail/bugs.hpp b/boost/numeric/interval/detail/bugs.hpp
index b9b421a230..e15bd0cfb3 100644
--- a/boost/numeric/interval/detail/bugs.hpp
+++ b/boost/numeric/interval/detail/bugs.hpp
@@ -1,7 +1,7 @@
/* Boost interval/detail/bugs.hpp file
*
* Copyright 2000 Jens Maurer
- * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/detail/c99_rounding_control.hpp b/boost/numeric/interval/detail/c99_rounding_control.hpp
index 71d13e787a..2ba7847f7a 100644
--- a/boost/numeric/interval/detail/c99_rounding_control.hpp
+++ b/boost/numeric/interval/detail/c99_rounding_control.hpp
@@ -1,7 +1,7 @@
/* Boost interval/detail/c99_rounding_control.hpp file
*
* Copyright 2000 Jens Maurer
- * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/detail/c99sub_rounding_control.hpp b/boost/numeric/interval/detail/c99sub_rounding_control.hpp
index 92c9b5c8a8..a8684df6a3 100644
--- a/boost/numeric/interval/detail/c99sub_rounding_control.hpp
+++ b/boost/numeric/interval/detail/c99sub_rounding_control.hpp
@@ -1,7 +1,7 @@
/* Boost interval/detail/c99sub_rounding_control.hpp file
*
* Copyright 2000 Jens Maurer
- * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/detail/interval_prototype.hpp b/boost/numeric/interval/detail/interval_prototype.hpp
index ac9029b70b..47ba447b65 100644
--- a/boost/numeric/interval/detail/interval_prototype.hpp
+++ b/boost/numeric/interval/detail/interval_prototype.hpp
@@ -1,6 +1,6 @@
/* Boost interval/detail/interval_prototype.hpp file
*
- * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/detail/msvc_rounding_control.hpp b/boost/numeric/interval/detail/msvc_rounding_control.hpp
index ccf1e8b476..2ad3fc19ce 100644
--- a/boost/numeric/interval/detail/msvc_rounding_control.hpp
+++ b/boost/numeric/interval/detail/msvc_rounding_control.hpp
@@ -1,7 +1,7 @@
/* Boost interval/detail/msvc_rounding_control.hpp file
*
* Copyright 2000 Maarten Keijzer
- * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
@@ -91,7 +91,7 @@ struct x86_rounding
{
_control87(hard2msvc(mode),
_MCW_EM | _MCW_RC
-#if !defined(_M_AMD64) && !defined(_M_ARM)
+#if !defined(_M_AMD64) && !defined(_M_ARM) && !defined(_M_ARM64)
// x64 ignores _MCW_PC and _MCW_IC, and the Debug CRT library actually
// asserts when these are passed to _control87.
// MSDN says on '_control87' that changing precision (_MCW_PC) or
diff --git a/boost/numeric/interval/detail/ppc_rounding_control.hpp b/boost/numeric/interval/detail/ppc_rounding_control.hpp
index d2cf4c80f3..87fe8ee665 100644
--- a/boost/numeric/interval/detail/ppc_rounding_control.hpp
+++ b/boost/numeric/interval/detail/ppc_rounding_control.hpp
@@ -1,7 +1,7 @@
/* Boost interval/detail/ppc_rounding_control.hpp file
*
* Copyright 2000 Jens Maurer
- * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
* Copyright 2005 Guillaume Melquiond
*
* Distributed under the Boost Software License, Version 1.0.
diff --git a/boost/numeric/interval/detail/sparc_rounding_control.hpp b/boost/numeric/interval/detail/sparc_rounding_control.hpp
index 6ba5baf038..2b08bec5cf 100644
--- a/boost/numeric/interval/detail/sparc_rounding_control.hpp
+++ b/boost/numeric/interval/detail/sparc_rounding_control.hpp
@@ -1,7 +1,7 @@
/* Boost interval/detail/sparc_rounding_control.hpp file
*
* Copyright 2000 Jens Maurer
- * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/detail/test_input.hpp b/boost/numeric/interval/detail/test_input.hpp
index 58695fec3c..9f93bb04ef 100644
--- a/boost/numeric/interval/detail/test_input.hpp
+++ b/boost/numeric/interval/detail/test_input.hpp
@@ -1,6 +1,6 @@
/* Boost interval/detail/test_input.hpp file
*
- * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/detail/x86_rounding_control.hpp b/boost/numeric/interval/detail/x86_rounding_control.hpp
index c35f16d914..3594d01691 100644
--- a/boost/numeric/interval/detail/x86_rounding_control.hpp
+++ b/boost/numeric/interval/detail/x86_rounding_control.hpp
@@ -1,7 +1,7 @@
/* Boost interval/detail/x86_rounding_control.hpp file
*
* Copyright 2000 Jens Maurer
- * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/detail/x86gcc_rounding_control.hpp b/boost/numeric/interval/detail/x86gcc_rounding_control.hpp
index 079d681df9..da5513b552 100644
--- a/boost/numeric/interval/detail/x86gcc_rounding_control.hpp
+++ b/boost/numeric/interval/detail/x86gcc_rounding_control.hpp
@@ -1,7 +1,7 @@
/* Boost interval/detail/x86gcc_rounding_control.hpp file
*
* Copyright 2000 Jens Maurer
- * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/ext/x86_fast_rounding_control.hpp b/boost/numeric/interval/ext/x86_fast_rounding_control.hpp
index 7f89a4e549..a505ead092 100644
--- a/boost/numeric/interval/ext/x86_fast_rounding_control.hpp
+++ b/boost/numeric/interval/ext/x86_fast_rounding_control.hpp
@@ -7,7 +7,7 @@
* overflow would happen without it. Indeed, only
* values in range are correctly rounded.
*
- * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/interval.hpp b/boost/numeric/interval/interval.hpp
index 0b2d0eec6e..e89af484fb 100644
--- a/boost/numeric/interval/interval.hpp
+++ b/boost/numeric/interval/interval.hpp
@@ -1,6 +1,6 @@
/* Boost interval/interval.hpp header file
*
- * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/limits.hpp b/boost/numeric/interval/limits.hpp
index 973681dbc5..36fd3a397b 100644
--- a/boost/numeric/interval/limits.hpp
+++ b/boost/numeric/interval/limits.hpp
@@ -1,7 +1,7 @@
/* Boost interval/limits.hpp template implementation file
*
* Copyright 2000 Jens Maurer
- * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/rounded_arith.hpp b/boost/numeric/interval/rounded_arith.hpp
index 2520274a6a..4bb869122a 100644
--- a/boost/numeric/interval/rounded_arith.hpp
+++ b/boost/numeric/interval/rounded_arith.hpp
@@ -1,6 +1,6 @@
/* Boost interval/rounded_arith.hpp template implementation file
*
- * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/rounded_transc.hpp b/boost/numeric/interval/rounded_transc.hpp
index ac4982e31c..ef6e28b3f9 100644
--- a/boost/numeric/interval/rounded_transc.hpp
+++ b/boost/numeric/interval/rounded_transc.hpp
@@ -1,6 +1,6 @@
/* Boost interval/rounded_transc.hpp template implementation file
*
- * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/rounding.hpp b/boost/numeric/interval/rounding.hpp
index f69e2e4b53..bf5b3c2719 100644
--- a/boost/numeric/interval/rounding.hpp
+++ b/boost/numeric/interval/rounding.hpp
@@ -1,6 +1,6 @@
/* Boost interval/rounding.hpp template implementation file
*
- * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/transc.hpp b/boost/numeric/interval/transc.hpp
index 8d7a7a1acd..b9b7e60c4e 100644
--- a/boost/numeric/interval/transc.hpp
+++ b/boost/numeric/interval/transc.hpp
@@ -1,7 +1,7 @@
/* Boost interval/transc.hpp template implementation file
*
* Copyright 2000 Jens Maurer
- * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/numeric/interval/utility.hpp b/boost/numeric/interval/utility.hpp
index c89cdb1e93..97c6bad81c 100644
--- a/boost/numeric/interval/utility.hpp
+++ b/boost/numeric/interval/utility.hpp
@@ -1,7 +1,7 @@
/* Boost interval/utility.hpp template implementation file
*
* Copyright 2000 Jens Maurer
- * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
+ * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
@@ -248,7 +248,6 @@ bisect(const interval<T, Policies>& x)
template<class T, class Policies> inline
T norm(const interval<T, Policies>& x)
{
- typedef interval<T, Policies> I;
if (interval_lib::detail::test_input(x)) {
typedef typename Policies::checking checking;
return checking::nan();
diff --git a/boost/numeric/odeint/integrate/integrate_n_steps.hpp b/boost/numeric/odeint/integrate/integrate_n_steps.hpp
index 7f3a49bddc..5cc8aa0e7b 100644
--- a/boost/numeric/odeint/integrate/integrate_n_steps.hpp
+++ b/boost/numeric/odeint/integrate/integrate_n_steps.hpp
@@ -23,6 +23,7 @@
#include <boost/numeric/odeint/stepper/stepper_categories.hpp>
#include <boost/numeric/odeint/integrate/null_observer.hpp>
#include <boost/numeric/odeint/integrate/detail/integrate_n_steps.hpp>
+#include <boost/numeric/odeint/integrate/check_adapter.hpp>
namespace boost {
namespace numeric {
diff --git a/boost/numeric/odeint/integrate/max_step_checker.hpp b/boost/numeric/odeint/integrate/max_step_checker.hpp
index 6808a57bdb..654c95bc7d 100644
--- a/boost/numeric/odeint/integrate/max_step_checker.hpp
+++ b/boost/numeric/odeint/integrate/max_step_checker.hpp
@@ -69,7 +69,7 @@ public:
if( m_steps++ >= m_max_steps )
{
char error_msg[200];
- sprintf(error_msg, "Max number of iterations exceeded (%d).", m_max_steps);
+ std::sprintf(error_msg, "Max number of iterations exceeded (%d).", m_max_steps);
BOOST_THROW_EXCEPTION( no_progress_error(error_msg) );
}
}
@@ -101,7 +101,7 @@ public:
if( m_steps++ >= m_max_steps )
{
char error_msg[200];
- sprintf(error_msg, "Max number of iterations exceeded (%d). A new step size was not found.", m_max_steps);
+ std::sprintf(error_msg, "Max number of iterations exceeded (%d). A new step size was not found.", m_max_steps);
BOOST_THROW_EXCEPTION( step_adjustment_error(error_msg) );
}
}
@@ -111,4 +111,4 @@ public:
} // namespace numeric
} // namespace boost
-#endif \ No newline at end of file
+#endif
diff --git a/boost/numeric/odeint/stepper/adams_bashforth_moulton.hpp b/boost/numeric/odeint/stepper/adams_bashforth_moulton.hpp
index 2f7cc4c6fb..f3edce1989 100644
--- a/boost/numeric/odeint/stepper/adams_bashforth_moulton.hpp
+++ b/boost/numeric/odeint/stepper/adams_bashforth_moulton.hpp
@@ -150,6 +150,12 @@ public :
}
+ void reset(void)
+ {
+ m_adams_bashforth.reset();
+ }
+
+
private:
@@ -175,7 +181,7 @@ private:
{
m_resizer.adjust_size( in , detail::bind( &stepper_type::template resize_impl< StateInOut > , detail::ref( *this ) , detail::_1 ) );
m_adams_bashforth.do_step( system , in , t , m_x.m_v , dt );
- m_adams_moulton.do_step( system , in , m_x.m_v , t , out , dt , m_adams_bashforth.step_storage() );
+ m_adams_moulton.do_step( system , in , m_x.m_v , t+dt , out , dt , m_adams_bashforth.step_storage() );
}
else
{
@@ -293,6 +299,11 @@ private:
* \param dt The step size.
*/
+ /**
+ * \fn adams_bashforth_moulton::reset( void )
+ * \brief Resets the internal buffers of the stepper.
+ */
+
} // odeint
} // numeric
diff --git a/boost/numeric/odeint/stepper/bulirsch_stoer.hpp b/boost/numeric/odeint/stepper/bulirsch_stoer.hpp
index 4b908333ba..02c37492b9 100644
--- a/boost/numeric/odeint/stepper/bulirsch_stoer.hpp
+++ b/boost/numeric/odeint/stepper/bulirsch_stoer.hpp
@@ -98,6 +98,7 @@ public:
m_interval_sequence( m_k_max+1 ) ,
m_coeff( m_k_max+1 ) ,
m_cost( m_k_max+1 ) ,
+ m_facmin_table( m_k_max+1 ) ,
m_table( m_k_max ) ,
STEPFAC1( 0.65 ) , STEPFAC2( 0.94 ) , STEPFAC3( 0.02 ) , STEPFAC4( 4.0 ) , KFAC1( 0.8 ) , KFAC2( 0.9 )
{
@@ -112,21 +113,14 @@ public:
else
m_cost[i] = m_cost[i-1] + m_interval_sequence[i];
m_coeff[i].resize(i);
+ m_facmin_table[i] = pow BOOST_PREVENT_MACRO_SUBSTITUTION( STEPFAC3 , static_cast< value_type >(1) / static_cast< value_type >( 2*i+1 ) );
for( size_t k = 0 ; k < i ; ++k )
{
const value_type r = static_cast< value_type >( m_interval_sequence[i] ) / static_cast< value_type >( m_interval_sequence[k] );
m_coeff[i][k] = 1.0 / ( r*r - static_cast< value_type >( 1.0 ) ); // coefficients for extrapolation
}
-
- // crude estimate of optimal order
-
- m_current_k_opt = 4;
- /* no calculation because log10 might not exist for value_type!
- const value_type logfact( -log10( max BOOST_PREVENT_MACRO_SUBSTITUTION( eps_rel , static_cast< value_type >(1.0E-12) ) ) * 0.6 + 0.5 );
- m_current_k_opt = max BOOST_PREVENT_MACRO_SUBSTITUTION( static_cast<value_type>( 1 ) , min BOOST_PREVENT_MACRO_SUBSTITUTION( static_cast<value_type>( m_k_max-1 ) , logfact ));
- */
}
-
+ reset();
}
@@ -282,7 +276,7 @@ public:
{
m_current_k_opt = min BOOST_PREVENT_MACRO_SUBSTITUTION( static_cast<int>(m_k_max-1) , static_cast<int>(m_current_k_opt)+1 );
new_h = h_opt[k];
- new_h *= m_cost[m_current_k_opt]/m_cost[k];
+ new_h *= static_cast<value_type>(m_cost[m_current_k_opt])/static_cast<value_type>(m_cost[k]);
} else
new_h = h_opt[m_current_k_opt];
break;
@@ -344,6 +338,12 @@ public:
{
m_first = true;
m_last_step_rejected = false;
+ // crude estimate of optimal order
+ m_current_k_opt = 4;
+ /* no calculation because log10 might not exist for value_type!
+ const value_type logfact( -log10( max BOOST_PREVENT_MACRO_SUBSTITUTION( eps_rel , static_cast< value_type >(1.0E-12) ) ) * 0.6 + 0.5 );
+ m_current_k_opt = max BOOST_PREVENT_MACRO_SUBSTITUTION( static_cast<value_type>( 1 ) , min BOOST_PREVENT_MACRO_SUBSTITUTION( static_cast<value_type>( m_k_max-1 ) , logfact ));
+ */
}
@@ -417,7 +417,7 @@ private:
BOOST_USING_STD_MAX();
using std::pow;
value_type expo( 1.0/(2*k+1) );
- value_type facmin = pow BOOST_PREVENT_MACRO_SUBSTITUTION( STEPFAC3 , expo );
+ value_type facmin = m_facmin_table[k];
value_type fac;
if (error == 0.0)
fac=1.0/facmin;
@@ -506,6 +506,7 @@ private:
int_vector m_interval_sequence; // stores the successive interval counts
value_matrix m_coeff;
int_vector m_cost; // costs for interval count
+ value_vector m_facmin_table; // for precomputed facmin to save pow calls
state_table_type m_table; // sequence of states for extrapolation
diff --git a/boost/numeric/odeint/stepper/bulirsch_stoer_dense_out.hpp b/boost/numeric/odeint/stepper/bulirsch_stoer_dense_out.hpp
index d876ca3d36..6a1eed15fb 100644
--- a/boost/numeric/odeint/stepper/bulirsch_stoer_dense_out.hpp
+++ b/boost/numeric/odeint/stepper/bulirsch_stoer_dense_out.hpp
@@ -110,6 +110,7 @@ public:
m_interval_sequence( m_k_max+1 ) ,
m_coeff( m_k_max+1 ) ,
m_cost( m_k_max+1 ) ,
+ m_facmin_table( m_k_max+1 ) ,
m_table( m_k_max ) ,
m_mp_states( m_k_max+1 ) ,
m_derivs( m_k_max+1 ) ,
@@ -125,9 +126,13 @@ public:
m_interval_sequence[i] = 2 + 4*i; // 2 6 10 14 ...
m_derivs[i].resize( m_interval_sequence[i] );
if( i == 0 )
+ {
m_cost[i] = m_interval_sequence[i];
- else
+ } else
+ {
m_cost[i] = m_cost[i-1] + m_interval_sequence[i];
+ }
+ m_facmin_table[i] = pow BOOST_PREVENT_MACRO_SUBSTITUTION( STEPFAC3 , static_cast< value_type >(1) / static_cast< value_type >( 2*i+1 ) );
m_coeff[i].resize(i);
for( size_t k = 0 ; k < i ; ++k )
{
@@ -429,7 +434,7 @@ private:
using std::pow;
value_type expo = static_cast<value_type>(1)/(m_interval_sequence[k-1]);
- value_type facmin = pow BOOST_PREVENT_MACRO_SUBSTITUTION( STEPFAC3 , expo );
+ value_type facmin = m_facmin_table[k];
value_type fac;
if (error == 0.0)
fac = static_cast<value_type>(1)/facmin;
@@ -692,6 +697,7 @@ private:
int_vector m_interval_sequence; // stores the successive interval counts
value_matrix m_coeff;
int_vector m_cost; // costs for interval count
+ value_vector m_facmin_table; // for precomputed facmin to save pow calls
state_vector_type m_table; // sequence of states for extrapolation
diff --git a/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp b/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp
index 8ae627fe1c..aac2b02dca 100644
--- a/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp
+++ b/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp
@@ -143,7 +143,7 @@ public:
error = max BOOST_PREVENT_MACRO_SUBSTITUTION (
static_cast<value_type>( pow( static_cast<value_type>(5.0) , -static_cast<value_type>(stepper_order) ) ) ,
error);
- time_type dt_old = dt;
+ // time_type dt_old = dt; unused variable warning
//error too small - increase dt and keep the evolution and limit scaling factor to 5.0
dt *= static_cast<value_type>(9)/static_cast<value_type>(10) *
pow(error, static_cast<value_type>(-1) / stepper_order);
diff --git a/boost/numeric/odeint/stepper/rosenbrock4_controller.hpp b/boost/numeric/odeint/stepper/rosenbrock4_controller.hpp
index 0e5edd32c0..61d6e51191 100644
--- a/boost/numeric/odeint/stepper/rosenbrock4_controller.hpp
+++ b/boost/numeric/odeint/stepper/rosenbrock4_controller.hpp
@@ -163,6 +163,8 @@ public:
if( m_max_dt != static_cast<time_type>(0) )
{
dt = detail::min_abs(m_max_dt, dt_new);
+ } else {
+ dt = dt_new;
}
m_last_rejected = false;
return success;
diff --git a/boost/parameter/aux_/arg_list.hpp b/boost/parameter/aux_/arg_list.hpp
index 71e4da271e..721ce04004 100644
--- a/boost/parameter/aux_/arg_list.hpp
+++ b/boost/parameter/aux_/arg_list.hpp
@@ -339,6 +339,7 @@ struct arg_list : Next
template <class Default>
reference operator[](lazy_default<key_type, Default>) const
{
+ BOOST_MPL_ASSERT_NOT((holds_maybe));
return arg.value;
}
diff --git a/boost/phoenix/config.hpp b/boost/phoenix/config.hpp
index 6d69394154..2afcd17a90 100644
--- a/boost/phoenix/config.hpp
+++ b/boost/phoenix/config.hpp
@@ -61,11 +61,15 @@
#define BOOST_PHOENIX_HASH_MAP_HEADER BOOST_HASH_MAP_HEADER
#define BOOST_PHOENIX_HAS_HASH
#define BOOST_PHOENIX_HASH_NAMESPACE BOOST_STD_EXTENSION_NAMESPACE
+#define BOOST_PHOENIX_HASH_template_rest_param class Hash, class Cmp, class Alloc
+#define BOOST_PHOENIX_HASH_type_rest_param Hash, Cmp, Alloc
#elif defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB < 610)
#define BOOST_PHOENIX_HASH_SET_HEADER <hash_set>
#define BOOST_PHOENIX_HASH_MAP_HEADER <hash_map>
#define BOOST_PHOENIX_HAS_HASH
#define BOOST_PHOENIX_HASH_NAMESPACE stdext
+#define BOOST_PHOENIX_HASH_template_rest_param class Tr, class Alloc
+#define BOOST_PHOENIX_HASH_type_rest_param Tr, Alloc
#endif
#if BOOST_WORKAROUND(BOOST_GCC, < 40100)
diff --git a/boost/phoenix/stl/algorithm/detail/is_std_hash_map.hpp b/boost/phoenix/stl/algorithm/detail/is_std_hash_map.hpp
index 7a02b4fd61..e100472fcc 100644
--- a/boost/phoenix/stl/algorithm/detail/is_std_hash_map.hpp
+++ b/boost/phoenix/stl/algorithm/detail/is_std_hash_map.hpp
@@ -15,8 +15,12 @@
#ifndef BOOST_PHOENIX_IS_STD_HASH_MAP_EN_16_12_2004
#define BOOST_PHOENIX_IS_STD_HASH_MAP_EN_16_12_2004
+#include <boost/phoenix/config.hpp>
#include <boost/mpl/bool.hpp>
-#include "./std_hash_map_fwd.hpp"
+
+#ifdef BOOST_PHOENIX_HAS_HASH
+#include BOOST_PHOENIX_HASH_MAP_HEADER
+#endif
namespace boost
{
@@ -30,49 +34,15 @@ namespace boost
: boost::mpl::false_
{};
-#ifdef BOOST_HAS_HASH
-
- template<
- class Kty
- , class Ty
- , class Hash
- , class Cmp
- , class Alloc
- >
- struct is_std_hash_map< ::BOOST_STD_EXTENSION_NAMESPACE::hash_map<Kty,Ty,Hash,Cmp,Alloc> >
- : boost::mpl::true_
- {};
-
- template<
- class Kty
- , class Ty
- , class Hash
- , class Cmp
- , class Alloc
- >
- struct is_std_hash_multimap< ::BOOST_STD_EXTENSION_NAMESPACE::hash_multimap<Kty,Ty,Hash,Cmp,Alloc> >
- : boost::mpl::true_
- {};
-
-#elif defined(BOOST_DINKUMWARE_STDLIB)
+#ifdef BOOST_PHOENIX_HAS_HASH
- template<
- class Kty
- , class Ty
- , class Tr
- , class Alloc
- >
- struct is_std_hash_map< ::BOOST_STD_EXTENSION_NAMESPACE::hash_map<Kty,Ty,Tr,Alloc> >
+ template<class Kty,class Ty,BOOST_PHOENIX_HASH_template_rest_param>
+ struct is_std_hash_map< ::BOOST_PHOENIX_HASH_NAMESPACE::hash_map<Kty,Ty,BOOST_PHOENIX_HASH_type_rest_param> >
: boost::mpl::true_
{};
- template<
- class Kty
- , class Ty
- , class Tr
- , class Alloc
- >
- struct is_std_hash_multimap< ::BOOST_STD_EXTENSION_NAMESPACE::hash_multimap<Kty,Ty,Tr,Alloc> >
+ template<class Kty,class Ty,BOOST_PHOENIX_HASH_template_rest_param>
+ struct is_std_hash_multimap< ::BOOST_PHOENIX_HASH_NAMESPACE::hash_multimap<Kty,Ty,BOOST_PHOENIX_HASH_type_rest_param> >
: boost::mpl::true_
{};
diff --git a/boost/phoenix/stl/algorithm/detail/is_std_hash_set.hpp b/boost/phoenix/stl/algorithm/detail/is_std_hash_set.hpp
index c6631ad705..d57785548a 100644
--- a/boost/phoenix/stl/algorithm/detail/is_std_hash_set.hpp
+++ b/boost/phoenix/stl/algorithm/detail/is_std_hash_set.hpp
@@ -15,8 +15,12 @@
#ifndef BOOST_PHOENIX_IS_STD_HASH_SET_EN_16_12_2004
#define BOOST_PHOENIX_IS_STD_HASH_SET_EN_16_12_2004
+#include <boost/phoenix/config.hpp>
#include <boost/mpl/bool.hpp>
-#include "./std_hash_set_fwd.hpp"
+
+#ifdef BOOST_PHOENIX_HAS_HASH
+#include BOOST_PHOENIX_HASH_SET_HEADER
+#endif
namespace boost
{
@@ -30,45 +34,15 @@ namespace boost
: boost::mpl::false_
{};
-#if defined(BOOST_HAS_HASH)
-
- template<
- class Kty
- , class Hash
- , class Cmp
- , class Alloc
- >
- struct is_std_hash_set< ::BOOST_STD_EXTENSION_NAMESPACE::hash_set<Kty,Hash,Cmp,Alloc> >
- : boost::mpl::true_
- {};
-
- template<
- class Kty
- , class Hash
- , class Cmp
- , class Alloc
- >
- struct is_std_hash_multiset< ::BOOST_STD_EXTENSION_NAMESPACE::hash_multiset<Kty,Hash,Cmp,Alloc> >
- : boost::mpl::true_
- {};
-
-#elif defined(BOOST_DINKUMWARE_STDLIB)
+#ifdef BOOST_PHOENIX_HAS_HASH
- template<
- class Kty
- , class Tr
- , class Alloc
- >
- struct is_std_hash_set< ::BOOST_STD_EXTENSION_NAMESPACE::hash_set<Kty,Tr,Alloc> >
+ template<class Kty,BOOST_PHOENIX_HASH_template_rest_param>
+ struct is_std_hash_set< ::BOOST_PHOENIX_HASH_NAMESPACE::hash_set<Kty,BOOST_PHOENIX_HASH_type_rest_param> >
: boost::mpl::true_
{};
- template<
- class Kty
- , class Tr
- , class Alloc
- >
- struct is_std_hash_multiset< ::BOOST_STD_EXTENSION_NAMESPACE::hash_multiset<Kty,Tr,Alloc> >
+ template<class Kty,BOOST_PHOENIX_HASH_template_rest_param>
+ struct is_std_hash_multiset< ::BOOST_PHOENIX_HASH_NAMESPACE::hash_multiset<Kty,BOOST_PHOENIX_HASH_type_rest_param> >
: boost::mpl::true_
{};
diff --git a/boost/phoenix/stl/algorithm/detail/is_std_list.hpp b/boost/phoenix/stl/algorithm/detail/is_std_list.hpp
index 390f592b7b..cc8d18fcaf 100644
--- a/boost/phoenix/stl/algorithm/detail/is_std_list.hpp
+++ b/boost/phoenix/stl/algorithm/detail/is_std_list.hpp
@@ -16,7 +16,7 @@
#define BOOST_PHOENIX_IS_STD_LIST_EN_16_12_2004
#include <boost/mpl/bool.hpp>
-#include <boost/detail/container_fwd.hpp>
+#include <list>
namespace boost
{
diff --git a/boost/phoenix/stl/algorithm/detail/is_std_map.hpp b/boost/phoenix/stl/algorithm/detail/is_std_map.hpp
index 58aba6220c..2aea278c42 100644
--- a/boost/phoenix/stl/algorithm/detail/is_std_map.hpp
+++ b/boost/phoenix/stl/algorithm/detail/is_std_map.hpp
@@ -16,7 +16,7 @@
#define BOOST_PHOENIX_IS_STD_MAP_EN_16_12_2004
#include <boost/mpl/bool.hpp>
-#include <boost/detail/container_fwd.hpp>
+#include <map>
namespace boost
{
diff --git a/boost/phoenix/stl/algorithm/detail/is_std_set.hpp b/boost/phoenix/stl/algorithm/detail/is_std_set.hpp
index e44a04765f..cbc4241ad2 100644
--- a/boost/phoenix/stl/algorithm/detail/is_std_set.hpp
+++ b/boost/phoenix/stl/algorithm/detail/is_std_set.hpp
@@ -20,7 +20,7 @@
#define BOOST_PHOENIX_IS_STD_SET_EN_16_12_2004
#include <boost/mpl/bool.hpp>
-#include <boost/detail/container_fwd.hpp>
+#include <set>
namespace boost
{
diff --git a/boost/phoenix/stl/algorithm/detail/is_unordered_set_or_map.hpp b/boost/phoenix/stl/algorithm/detail/is_unordered_set_or_map.hpp
index 5a4be127b5..54b5f2f408 100644
--- a/boost/phoenix/stl/algorithm/detail/is_unordered_set_or_map.hpp
+++ b/boost/phoenix/stl/algorithm/detail/is_unordered_set_or_map.hpp
@@ -20,8 +20,13 @@
#ifndef BOOST_PHOENIX_IS_STD_UNORDERED_SET_OR_MAP
#define BOOST_PHOENIX_IS_STD_UNORDERED_SET_OR_MAP
+#include <boost/phoenix/config.hpp>
#include <boost/mpl/bool.hpp>
-#include "./std_unordered_set_or_map_fwd.hpp"
+
+#ifdef BOOST_PHOENIX_HAS_UNORDERED_SET_AND_MAP
+#include BOOST_PHOENIX_UNORDERED_SET_HEADER
+#include BOOST_PHOENIX_UNORDERED_MAP_HEADER
+#endif
namespace boost
{
diff --git a/boost/phoenix/stl/algorithm/detail/std_hash_map_fwd.hpp b/boost/phoenix/stl/algorithm/detail/std_hash_map_fwd.hpp
deleted file mode 100644
index 3688897fa3..0000000000
--- a/boost/phoenix/stl/algorithm/detail/std_hash_map_fwd.hpp
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2005 Daniel Wallin.
-// Copyright 2005 Joel de Guzman.
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-//
-// Modeled after range_ex, Copyright 2004 Eric Niebler
-///////////////////////////////////////////////////////////////////////////////
-//
-// std_hash_map_fwd.hpp
-//
-/////////////////////////////////////////////////////////////////////////////
-
-#if defined(_MSC_VER)
-# pragma once
-#endif
-
-#ifndef BOOST_PHOENIX_STD_HASH_MAP_FWD_EN_16_12_2004
-#define BOOST_PHOENIX_STD_HASH_MAP_FWD_EN_16_12_2004
-
-#include <boost/phoenix/config.hpp>
-
-#if defined(BOOST_HAS_HASH)
-
-namespace BOOST_STD_EXTENSION_NAMESPACE
-{
- template<
- class Kty
- , class Ty
- , class Hash
- , class Cmp
- , class Alloc
- >
- class hash_map;
-
- template<
- class Kty
- , class Ty
- , class Hash
- , class Cmp
- , class Alloc
- >
- class hash_multimap;
-}
-
-#elif defined(BOOST_DINKUMWARE_STDLIB)
-
-namespace BOOST_STD_EXTENSION_NAMESPACE
-{
- template<
- class Kty
- , class Ty
- , class Tr
- , class Alloc
- >
- class hash_map;
-
- template<
- class Kty
- , class Ty
- , class Tr
- , class Alloc
- >
- class hash_multimap;
-}
-
-#endif
-
-#endif
diff --git a/boost/phoenix/stl/algorithm/detail/std_hash_set_fwd.hpp b/boost/phoenix/stl/algorithm/detail/std_hash_set_fwd.hpp
deleted file mode 100644
index 54049db891..0000000000
--- a/boost/phoenix/stl/algorithm/detail/std_hash_set_fwd.hpp
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2005 Daniel Wallin.
-// Copyright 2005 Joel de Guzman.
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-//
-// Modeled after range_ex, Copyright 2004 Eric Niebler
-///////////////////////////////////////////////////////////////////////////////
-//
-// std_hash_set_fwd.hpp
-//
-/////////////////////////////////////////////////////////////////////////////
-
-#ifndef BOOST_PHOENIX_STD_HASH_SET_FWD_EN_16_12_2004
-#define BOOST_PHOENIX_STD_HASH_SET_FWD_EN_16_12_2004
-
-#include <boost/phoenix/config.hpp>
-
-#if defined(BOOST_HAS_HASH)
-
-namespace BOOST_STD_EXTENSION_NAMESPACE
-{
- template<
- class Kty
- , class Hash
- , class Cmp
- , class Alloc
- >
- class hash_set;
-
- template<
- class Kty
- , class Hash
- , class Cmp
- , class Alloc
- >
- class hash_multiset;
-}
-
-#elif defined(BOOST_DINKUMWARE_STDLIB)
-
-namespace BOOST_STD_EXTENSION_NAMESPACE
-{
- template<
- class Kty
- , class Tr
- , class Alloc
- >
- class hash_set;
-
- template<
- class Kty
- , class Tr
- , class Alloc
- >
- class hash_multiset;
-}
-
-#endif
-
-#endif
diff --git a/boost/phoenix/stl/algorithm/detail/std_unordered_set_or_map_fwd.hpp b/boost/phoenix/stl/algorithm/detail/std_unordered_set_or_map_fwd.hpp
deleted file mode 100644
index e650328d15..0000000000
--- a/boost/phoenix/stl/algorithm/detail/std_unordered_set_or_map_fwd.hpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/////////////////////////////////////////////////////////////////////////////
-// Copyright 2005 Daniel Wallin.
-// Copyright 2005 Joel de Guzman.
-// Copyright 2015 John Fletcher
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-//
-// Modeled after range_ex, Copyright 2004 Eric Niebler
-///////////////////////////////////////////////////////////////////////////////
-//
-// std_unordered_set_or_map_fwd.hpp
-//
-/////////////////////////////////////////////////////////////////////////////
-
-#ifndef BOOST_PHOENIX_STD_UNORDERED_SET_OR_MAP_FWD
-#define BOOST_PHOENIX_STD_UNORDERED_SET_OR_MAP_FWD
-
-#include <boost/phoenix/config.hpp>
-
-#ifdef BOOST_PHOENIX_HAS_UNORDERED_SET_AND_MAP
-#if defined(BOOST_PHOENIX_USING_LIBCPP) \
- || (defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB < 540))
-// Advance declaration not working for libc++ and MSVC 10
-#include BOOST_PHOENIX_UNORDERED_SET_HEADER
-#include BOOST_PHOENIX_UNORDERED_MAP_HEADER
-#else
-
-
-
-namespace std {
-
-
- template<
- class Kty
- , class Hash
- , class Cmp
- , class Alloc
- >
- class unordered_set;
-
- template<
- class Kty
- , class Hash
- , class Cmp
- , class Alloc
- >
- class unordered_multiset;
-
- template<
- class Kty
- , class Ty
- , class Hash
- , class Cmp
- , class Alloc
- >
- class unordered_map;
-
- template<
- class Kty
- , class Ty
- , class Hash
- , class Cmp
- , class Alloc
- >
- class unordered_multimap;
-}
-#endif
-
-
-#endif
-
-#endif
diff --git a/boost/phoenix/stl/algorithm/transformation.hpp b/boost/phoenix/stl/algorithm/transformation.hpp
index 37fd967af1..88389c1270 100644
--- a/boost/phoenix/stl/algorithm/transformation.hpp
+++ b/boost/phoenix/stl/algorithm/transformation.hpp
@@ -515,6 +515,7 @@ namespace boost { namespace phoenix { namespace impl
}
};
+#ifndef BOOST_NO_CXX98_RANDOM_SHUFFLE
struct random_shuffle
{
typedef void result_type;
@@ -531,6 +532,7 @@ namespace boost { namespace phoenix { namespace impl
return std::random_shuffle(detail::begin_(r), detail::end_(r), g);
}
};
+#endif
struct partition
{
@@ -1148,8 +1150,10 @@ namespace boost { namespace phoenix
BOOST_PHOENIX_ADAPT_CALLABLE(reverse_copy, impl::reverse_copy, 2)
BOOST_PHOENIX_ADAPT_CALLABLE(rotate, impl::rotate, 2)
BOOST_PHOENIX_ADAPT_CALLABLE(rotate_copy, impl::rotate_copy, 3)
+#ifndef BOOST_NO_CXX98_RANDOM_SHUFFLE
BOOST_PHOENIX_ADAPT_CALLABLE(random_shuffle, impl::random_shuffle, 1)
BOOST_PHOENIX_ADAPT_CALLABLE(random_shuffle, impl::random_shuffle, 2)
+#endif
BOOST_PHOENIX_ADAPT_CALLABLE(partition, impl::partition, 2)
BOOST_PHOENIX_ADAPT_CALLABLE(stable_partition, impl::stable_partition, 2)
BOOST_PHOENIX_ADAPT_CALLABLE(sort, impl::sort, 1)
diff --git a/boost/phoenix/stl/container/container.hpp b/boost/phoenix/stl/container/container.hpp
index 907b0eb6cd..d2b8c24ac0 100644
--- a/boost/phoenix/stl/container/container.hpp
+++ b/boost/phoenix/stl/container/container.hpp
@@ -33,7 +33,7 @@ namespace boost { namespace phoenix
// Lazy functions are provided for all of the member functions of the
// following containers:
//
-// deque - list - map - multimap - vector.
+// deque - list - map - multimap - vector - set - multiset.
//
// Indeed, should *your* class have member functions with the same names
// and signatures as those listed below, then it will automatically be
@@ -286,32 +286,25 @@ namespace boost { namespace phoenix
template <typename C, typename Arg1, typename Arg2 = mpl::void_>
struct erase
{
- // BOOST_MSVC #if branch here in map_erase_result non-
- // standard behavior. The return type should be void but
- // VC7.1 prefers to return iterator_of<C>. As a result,
- // VC7.1 complains of error C2562:
- // boost::phoenix::stl::erase::operator() 'void' function
- // returning a value. Oh well... :*
-
+ // MSVC and libc++ always returns iterator even in C++03 mode.
typedef
- boost::mpl::eval_if_c<
- boost::is_same<
- typename remove_reference<Arg1>::type
- , typename iterator_of<C>::type
- >::value
-#if defined(BOOST_MSVC)// && (BOOST_MSVC <= 1500)
+ boost::mpl::eval_if<
+ is_key_type_of<C, Arg1>
+ , size_type_of<C>
+#if defined(BOOST_MSVC) /*&& (BOOST_MSVC <= 1500)*/ \
+ && (defined(BOOST_LIBSTDCXX11) && 40500 <= BOOST_LIBSTDCXX_VERSION) \
+ && defined(_LIBCPP_VERSION)
, iterator_of<C>
#else
, boost::mpl::identity<void>
#endif
- , size_type_of<C>
>
- map_erase_result;
+ assoc_erase_result;
typedef typename
boost::mpl::eval_if_c<
- has_mapped_type<C>::value
- , map_erase_result
+ has_key_type<C>::value
+ , assoc_erase_result
, iterator_of<C>
>::type
type;
@@ -322,18 +315,20 @@ namespace boost { namespace phoenix
{
// This mouthful can differentiate between the generic erase
// functions (Container == std::deque, std::list, std::vector) and
- // that specific to the two map-types, std::map and std::multimap.
+ // that specific to Associative Containers.
//
// where C is a std::deque, std::list, std::vector:
//
// 1) iterator C::erase(iterator where);
// 2) iterator C::erase(iterator first, iterator last);
//
- // where M is a std::map or std::multimap:
+ // where C is a std::map, std::multimap, std::set, or std::multiset:
//
// 3) size_type M::erase(const Key& keyval);
- // 4) void M::erase(iterator where);
- // 5) void M::erase(iterator first, iterator last);
+ // 4-a) void M::erase(iterator where);
+ // 4-b) iterator M::erase(iterator where);
+ // 5-a) void M::erase(iterator first, iterator last);
+ // 5-b) iterator M::erase(iterator first, iterator last);
template <typename Sig>
struct result;
diff --git a/boost/phoenix/stl/container/detail/container.hpp b/boost/phoenix/stl/container/detail/container.hpp
index fb6cad2fe9..b92472b237 100644
--- a/boost/phoenix/stl/container/detail/container.hpp
+++ b/boost/phoenix/stl/container/detail/container.hpp
@@ -12,6 +12,7 @@
#include <boost/mpl/eval_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/is_convertible.hpp>
namespace boost { namespace phoenix { namespace stl
{
@@ -110,8 +111,8 @@ namespace boost { namespace phoenix { namespace stl
//
// has_mapped_type<C>
//
-// Given a container C, determine if it is a map or multimap
-// by checking if it has a member type named "mapped_type".
+// Given a container C, determine if it is a map, multimap, unordered_map,
+// or unordered_multimap by checking if it has a member type named "mapped_type".
//
///////////////////////////////////////////////////////////////////////////////
namespace stl_impl
@@ -135,6 +136,43 @@ namespace boost { namespace phoenix { namespace stl
///////////////////////////////////////////////////////////////////////////////
//
+// has_key_type<C>
+//
+// Given a container C, determine if it is a Associative Container
+// by checking if it has a member type named "key_type".
+//
+///////////////////////////////////////////////////////////////////////////////
+ namespace stl_impl
+ {
+ template <typename C>
+ one has_key_type(typename C::key_type(*)());
+
+ template <typename C>
+ two has_key_type(...);
+ }
+
+ template <typename C>
+ struct has_key_type
+ : boost::mpl::bool_<
+ sizeof(stl_impl::has_key_type<C>(0)) == sizeof(stl_impl::one)
+ >
+ {};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// is_key_type_of<C, Arg>
+//
+// Lazy evaluation friendly predicate.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+ template <typename C, typename Arg>
+ struct is_key_type_of
+ : boost::is_convertible<Arg, typename key_type_of<C>::type>
+ {};
+
+///////////////////////////////////////////////////////////////////////////////
+//
// map_insert_returns_pair<C>
//
// Distinguish a map from a multimap by checking the return type
diff --git a/boost/pointer_cast.hpp b/boost/pointer_cast.hpp
index 5af497170d..d47327bc70 100644
--- a/boost/pointer_cast.hpp
+++ b/boost/pointer_cast.hpp
@@ -11,33 +11,34 @@
#define BOOST_POINTER_CAST_HPP
#include <boost/config.hpp>
+#include <boost/smart_ptr/detail/sp_noexcept.hpp>
namespace boost {
//static_pointer_cast overload for raw pointers
template<class T, class U>
-inline T* static_pointer_cast(U *ptr)
+inline T* static_pointer_cast(U *ptr) BOOST_SP_NOEXCEPT
{
return static_cast<T*>(ptr);
}
//dynamic_pointer_cast overload for raw pointers
template<class T, class U>
-inline T* dynamic_pointer_cast(U *ptr)
+inline T* dynamic_pointer_cast(U *ptr) BOOST_SP_NOEXCEPT
{
return dynamic_cast<T*>(ptr);
}
//const_pointer_cast overload for raw pointers
template<class T, class U>
-inline T* const_pointer_cast(U *ptr)
+inline T* const_pointer_cast(U *ptr) BOOST_SP_NOEXCEPT
{
return const_cast<T*>(ptr);
}
//reinterpret_pointer_cast overload for raw pointers
template<class T, class U>
-inline T* reinterpret_pointer_cast(U *ptr)
+inline T* reinterpret_pointer_cast(U *ptr) BOOST_SP_NOEXCEPT
{
return reinterpret_cast<T*>(ptr);
}
@@ -62,7 +63,7 @@ using std::dynamic_pointer_cast;
using std::const_pointer_cast;
//reinterpret_pointer_cast overload for std::shared_ptr
-template<class T, class U> std::shared_ptr<T> reinterpret_pointer_cast(const std::shared_ptr<U> & r ) BOOST_NOEXCEPT
+template<class T, class U> std::shared_ptr<T> reinterpret_pointer_cast(const std::shared_ptr<U> & r ) BOOST_SP_NOEXCEPT
{
(void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
@@ -73,7 +74,7 @@ template<class T, class U> std::shared_ptr<T> reinterpret_pointer_cast(const std
}
//static_pointer_cast overload for std::unique_ptr
-template<class T, class U> std::unique_ptr<T> static_pointer_cast( std::unique_ptr<U> && r ) BOOST_NOEXCEPT
+template<class T, class U> std::unique_ptr<T> static_pointer_cast( std::unique_ptr<U> && r ) BOOST_SP_NOEXCEPT
{
(void) static_cast< T* >( static_cast< U* >( 0 ) );
@@ -83,7 +84,7 @@ template<class T, class U> std::unique_ptr<T> static_pointer_cast( std::unique_p
}
//dynamic_pointer_cast overload for std::unique_ptr
-template<class T, class U> std::unique_ptr<T> dynamic_pointer_cast( std::unique_ptr<U> && r ) BOOST_NOEXCEPT
+template<class T, class U> std::unique_ptr<T> dynamic_pointer_cast( std::unique_ptr<U> && r ) BOOST_SP_NOEXCEPT
{
(void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
@@ -95,7 +96,7 @@ template<class T, class U> std::unique_ptr<T> dynamic_pointer_cast( std::unique_
}
//const_pointer_cast overload for std::unique_ptr
-template<class T, class U> std::unique_ptr<T> const_pointer_cast( std::unique_ptr<U> && r ) BOOST_NOEXCEPT
+template<class T, class U> std::unique_ptr<T> const_pointer_cast( std::unique_ptr<U> && r ) BOOST_SP_NOEXCEPT
{
(void) const_cast< T* >( static_cast< U* >( 0 ) );
@@ -105,7 +106,7 @@ template<class T, class U> std::unique_ptr<T> const_pointer_cast( std::unique_pt
}
//reinterpret_pointer_cast overload for std::unique_ptr
-template<class T, class U> std::unique_ptr<T> reinterpret_pointer_cast( std::unique_ptr<U> && r ) BOOST_NOEXCEPT
+template<class T, class U> std::unique_ptr<T> reinterpret_pointer_cast( std::unique_ptr<U> && r ) BOOST_SP_NOEXCEPT
{
(void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
diff --git a/boost/pointer_to_other.hpp b/boost/pointer_to_other.hpp
index 85167349cf..d7d455dc6e 100644
--- a/boost/pointer_to_other.hpp
+++ b/boost/pointer_to_other.hpp
@@ -12,7 +12,7 @@
// (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/pointer_to_other.html
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
//
namespace boost
diff --git a/boost/poly_collection/algorithm.hpp b/boost/poly_collection/algorithm.hpp
new file mode 100644
index 0000000000..ed59bf4ded
--- /dev/null
+++ b/boost/poly_collection/algorithm.hpp
@@ -0,0 +1,1065 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_ALGORITHM_HPP
+#define BOOST_POLY_COLLECTION_ALGORITHM_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <algorithm>
+#include <boost/poly_collection/detail/auto_iterator.hpp>
+#include <boost/poly_collection/detail/functional.hpp>
+#include <boost/poly_collection/detail/iterator_traits.hpp>
+#include <boost/poly_collection/detail/segment_split.hpp>
+#include <boost/poly_collection/detail/type_restitution.hpp>
+#include <iterator>
+#include <type_traits>
+#include <utility>
+
+/* Improved performance versions of std algorithms over poly_collection.
+ * poly_collection::alg is expected to be faster than the homonym std::alg
+ * because the latter does a traversal over a segmented structured, where
+ * incrementing requires checking for segment change, whereas the former
+ * for-loops over flat segments.
+ * Additionally, poly_collection::alg<Ti...>(...,f) *restitutes* Ti when
+ * passing elements to f, i.e. if the concrete type of the element is Ti
+ * then f is invoked with a [const] Ti&, which can dramatically improve
+ * performance when f has specific overloads for Ti (like, for instance,
+ * generic lambdas) as static optimization can kick in (devirtualization
+ * being a particular example).
+ */
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+namespace algorithm{
+
+template<typename Iterator>
+using enable_if_poly_collection_iterator=typename std::enable_if<
+ !std::is_void<typename poly_collection_of<Iterator>::type>::value
+>::type*;
+
+BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_all_of,std::all_of)
+
+template<
+ typename... Ts,typename Iterator,typename Predicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+bool all_of(const Iterator& first,const Iterator& last,Predicate pred)
+{
+ auto alg=restitute_range<Ts...>(std_all_of{},pred);
+ for(auto i:detail::segment_split(first,last))if(!alg(i))return false;
+ return true;
+}
+
+BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_any_of,std::any_of)
+
+template<
+ typename... Ts,typename Iterator,typename Predicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+bool any_of(const Iterator& first,const Iterator& last,Predicate pred)
+{
+ auto alg=restitute_range<Ts...>(std_any_of{},pred);
+ for(auto i:detail::segment_split(first,last))if(alg(i))return true;
+ return false;
+}
+
+BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_none_of,std::none_of)
+
+template<
+ typename... Ts,typename Iterator,typename Predicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+bool none_of(const Iterator& first,const Iterator& last,Predicate pred)
+{
+ auto alg=restitute_range<Ts...>(std_none_of{},pred);
+ for(auto i:detail::segment_split(first,last))if(!alg(i))return false;
+ return true;
+}
+
+struct for_each_alg
+{
+ template<typename InputIterator,typename Function>
+ void operator()(
+ InputIterator first,InputIterator last,Function& f)const /* note the & */
+ {
+ for(;first!=last;++first)f(*first);
+ }
+};
+
+template<
+ typename... Ts,typename Iterator,typename Function,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+Function for_each(const Iterator& first,const Iterator& last,Function f)
+{
+ for_each_segment(first,last,restitute_range<Ts...>(for_each_alg{},f));
+ return std::move(f);
+}
+
+template<
+ typename Algorithm,typename... Ts,
+ typename Iterator,typename... Args,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+Iterator generic_find(
+ const Iterator& first,const Iterator& last,Args&&... args)
+{
+ using traits=iterator_traits<Iterator>;
+ using local_base_iterator=typename traits::local_base_iterator;
+
+ auto alg=restitute_range<Ts...>(
+ cast_return<local_base_iterator>(Algorithm{}),
+ std::forward<Args>(args)...);
+ for(auto i:detail::segment_split(first,last)){
+ auto it=alg(i);
+ if(it!=i.end())
+ return traits::iterator_from(
+ it,traits::end_base_segment_info_iterator_from(last));
+ }
+ return last;
+}
+
+BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_find,std::find)
+
+template<
+ typename... Ts,typename Iterator,typename T,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+Iterator find(const Iterator& first,const Iterator& last,const T& x)
+{
+ return generic_find<std_find,Ts...>(first,last,x);
+}
+
+BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_find_if,std::find_if)
+
+template<
+ typename... Ts,typename Iterator,typename Predicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+Iterator find_if(const Iterator& first,const Iterator& last,Predicate pred)
+{
+ return generic_find<std_find_if,Ts...>(first,last,pred);
+}
+
+BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_find_if_not,std::find_if_not)
+
+template<
+ typename... Ts,typename Iterator,typename Predicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+Iterator find_if_not(const Iterator& first,const Iterator& last,Predicate pred)
+{
+ return generic_find<std_find_if_not,Ts...>(first,last,pred);
+}
+
+/* find_end defined after search below */
+
+BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_find_first_of,std::find_first_of)
+
+template<
+ typename... Ts,typename Iterator,typename ForwardIterator,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+Iterator find_first_of(
+ const Iterator& first1,const Iterator& last1,
+ ForwardIterator first2,ForwardIterator last2)
+{
+ return generic_find<std_find_first_of,Ts...>(first1,last1,first2,last2);
+}
+
+template<
+ typename... Ts,typename Iterator,
+ typename ForwardIterator,typename BinaryPredicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+Iterator find_first_of(
+ const Iterator& first1,const Iterator& last1,
+ ForwardIterator first2,ForwardIterator last2,BinaryPredicate pred)
+{
+ return generic_find<std_find_first_of,Ts...>(first1,last1,first2,last2,pred);
+}
+
+template<typename... Ts>
+struct adjacent_find_alg
+{
+ template<
+ typename LocalIterator,typename BinaryPredicate,typename LocalBaseIterator
+ >
+ LocalBaseIterator operator()(
+ LocalIterator first,LocalIterator last,BinaryPredicate pred,
+ bool& carry,const std::type_info* prev_info, /* note the &s */
+ LocalBaseIterator& prev)const
+ {
+ if(first==last)return LocalBaseIterator{last};
+ if(carry){
+ auto p=restitute_iterator<Ts...>(deref_to(pred));
+ if(p(*prev_info,prev,first))return prev;
+ }
+ auto res=std::adjacent_find(first,last,pred);
+ if(res==last){
+ carry=true;
+ prev_info=&typeid(
+ typename std::iterator_traits<LocalIterator>::value_type);
+ prev=LocalBaseIterator{last-1};
+ }
+ else carry=false;
+ return LocalBaseIterator{res};
+ }
+};
+
+template<
+ typename... Ts,typename Iterator,typename BinaryPredicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+Iterator adjacent_find(
+ const Iterator& first,const Iterator& last,BinaryPredicate pred)
+{
+ using traits=iterator_traits<Iterator>;
+ using local_base_iterator=typename traits::local_base_iterator;
+
+ bool carry=false;
+ const std::type_info* prev_info{&typeid(void)};
+ local_base_iterator prev;
+ return generic_find<adjacent_find_alg<Ts...>,Ts...>(
+ first,last,pred,carry,prev_info,prev);
+}
+
+template<
+ typename... Ts,typename Iterator,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+Iterator adjacent_find(const Iterator& first,const Iterator& last)
+{
+ return algorithm::adjacent_find<Ts...>(first,last,transparent_equal_to{});
+}
+
+template<
+ typename Algorithm,typename... Ts,
+ typename Iterator,typename... Args,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+std::ptrdiff_t generic_count(
+ const Iterator& first,const Iterator& last,Args&&... args)
+{
+ auto alg=restitute_range<Ts...>(Algorithm{},std::forward<Args>(args)...);
+ std::ptrdiff_t res=0;
+ for(auto i:detail::segment_split(first,last))res+=alg(i);
+ return res;
+}
+
+BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_count,std::count)
+
+template<
+ typename... Ts,typename Iterator,typename T,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+std::ptrdiff_t count(const Iterator& first,const Iterator& last,const T& x)
+{
+ return generic_count<std_count,Ts...>(first,last,x);
+}
+
+BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_count_if,std::count_if)
+
+template<
+ typename... Ts,typename Iterator,typename Predicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+std::ptrdiff_t count_if(
+ const Iterator& first,const Iterator& last,Predicate pred)
+{
+ return generic_count<std_count_if,Ts...>(first,last,pred);
+}
+
+struct mismatch_alg
+{
+ template<
+ typename InputIterator1,
+ typename InputIterator2,typename BinaryPredicate
+ >
+ InputIterator1 operator()(
+ InputIterator1 first1,InputIterator1 last1,
+ InputIterator2& first2,BinaryPredicate pred)const /* note the & */
+ {
+ while(first1!=last1&&pred(*first1,*first2)){
+ ++first1;
+ ++first2;
+ }
+ return first1;
+ }
+
+ template<
+ typename InputIterator1,
+ typename InputIterator2,typename BinaryPredicate
+ >
+ InputIterator1 operator()(
+ InputIterator1 first1,InputIterator1 last1,
+ InputIterator2& first2,InputIterator2 last2, /* note the & */
+ BinaryPredicate pred)const
+ {
+ while(first1!=last1&&first2!=last2&&pred(*first1,*first2)){
+ ++first1;
+ ++first2;
+ }
+ return first1;
+ }
+};
+
+template<
+ typename... Ts,typename Iterator,
+ typename InputIterator,typename BinaryPredicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+std::pair<Iterator,InputIterator> mismatch(
+ const Iterator& first1,const Iterator& last1,
+ InputIterator first2,BinaryPredicate pred)
+{
+ auto it=generic_find<mismatch_alg,Ts...>(first1,last1,first2,pred);
+ return {it,first2};
+}
+
+template<
+ typename... Ts,typename Iterator,typename InputIterator,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+std::pair<Iterator,InputIterator> mismatch(
+ const Iterator& first1,const Iterator& last1,InputIterator first2)
+{
+ return algorithm::mismatch<Ts...>(
+ first1,last1,first2,transparent_equal_to{});
+}
+
+template<
+ typename... Ts,typename Iterator,
+ typename InputIterator,typename BinaryPredicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+std::pair<Iterator,InputIterator> mismatch(
+ const Iterator& first1,const Iterator& last1,
+ InputIterator first2,InputIterator last2,BinaryPredicate pred)
+{
+ auto it=generic_find<mismatch_alg,Ts...>(first1,last1,first2,last2,pred);
+ return {it,first2};
+}
+
+template<
+ typename... Ts,typename Iterator,typename InputIterator,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+std::pair<Iterator,InputIterator> mismatch(
+ const Iterator& first1,const Iterator& last1,
+ InputIterator first2,InputIterator last2)
+{
+ return algorithm::mismatch<Ts...>(
+ first1,last1,first2,last2,transparent_equal_to{});
+}
+
+struct equal_alg
+{
+ template<
+ typename InputIterator1,
+ typename InputIterator2,typename BinaryPredicate
+ >
+ bool operator()(
+ InputIterator1 first1,InputIterator1 last1,
+ InputIterator2& first2,BinaryPredicate pred)const /* note the & */
+ {
+ for(;first1!=last1;++first1,++first2){
+ if(!pred(*first1,*first2))return false;
+ }
+ return true;
+ }
+
+ template<
+ typename InputIterator1,
+ typename InputIterator2,typename BinaryPredicate
+ >
+ bool operator()(
+ InputIterator1 first1,InputIterator1 last1,
+ InputIterator2& first2,InputIterator2 last2, /* note the & */
+ BinaryPredicate pred)const
+ {
+ for(;first1!=last1&&first2!=last2;++first1,++first2){
+ if(!pred(*first1,*first2))return false;
+ }
+ return first1==last1; /* don't check first2==last2 as op is partial */
+ }
+};
+
+template<
+ typename... Ts,typename Iterator,
+ typename InputIterator,typename BinaryPredicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+bool equal(
+ const Iterator& first1,const Iterator& last1,
+ InputIterator first2,BinaryPredicate pred)
+{
+ auto alg=restitute_range<Ts...>(equal_alg{},first2,pred);
+ for(auto i:detail::segment_split(first1,last1))if(!alg(i))return false;
+ return true;
+}
+
+template<
+ typename... Ts,typename Iterator,typename InputIterator,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+bool equal(
+ const Iterator& first1,const Iterator& last1,InputIterator first2)
+{
+ return algorithm::equal<Ts...>(first1,last1,first2,transparent_equal_to{});
+}
+
+template<
+ typename... Ts,typename Iterator,
+ typename InputIterator,typename BinaryPredicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+bool equal(
+ const Iterator& first1,const Iterator& last1,
+ InputIterator first2,InputIterator last2,BinaryPredicate pred)
+{
+ auto alg=restitute_range<Ts...>(equal_alg{},first2,last2,pred);
+ for(auto i:detail::segment_split(first1,last1))if(!alg(i))return false;
+ return first2==last2;
+}
+
+template<
+ typename... Ts,typename Iterator,typename InputIterator,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+bool equal(
+ const Iterator& first1,const Iterator& last1,
+ InputIterator first2,InputIterator last2)
+{
+ return algorithm::equal<Ts...>(
+ first1,last1,first2,last2,transparent_equal_to{});
+}
+
+template<
+ typename... Ts,typename Iterator,
+ typename ForwardIterator,typename BinaryPredicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+bool is_permutation_suffix(
+ const Iterator& first1,const Iterator& last1,
+ ForwardIterator first2,ForwardIterator last2,BinaryPredicate pred)
+{
+ using traits=iterator_traits<Iterator>;
+
+ auto send=traits::end_base_segment_info_iterator_from(last1);
+ for(auto i:detail::segment_split(first1,last1)){
+ for(auto lbscan=i.begin();lbscan!=i.end();++lbscan){
+ auto& info=i.type_info();
+ auto p=head_closure(
+ restitute_iterator<Ts...>(deref_1st_to(pred)),info,lbscan);
+ auto scan=traits::iterator_from(lbscan,send);
+ if(algorithm::find_if<Ts...>(first1,scan,p)!=scan)continue;
+ std::ptrdiff_t matches=std::count_if(first2,last2,p);
+ if(matches==0||
+ matches!=algorithm::count_if<Ts...>(scan,last1,p))return false;
+ }
+ }
+ return true;
+}
+
+template<
+ typename... Ts,typename Iterator,
+ typename ForwardIterator,typename BinaryPredicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+bool is_permutation(
+ Iterator first1,Iterator last1,ForwardIterator first2,BinaryPredicate pred)
+{
+ std::tie(first1,first2)=algorithm::mismatch<Ts...>(first1,last1,first2,pred);
+ auto last2=std::next(first2,std::distance(first1,last1));
+ return is_permutation_suffix<Ts...>(first1,last1,first2,last2,pred);
+}
+
+template<
+ typename... Ts,typename Iterator,typename ForwardIterator,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+bool is_permutation(
+ const Iterator& first1,const Iterator& last1,ForwardIterator first2)
+{
+ return algorithm::is_permutation<Ts...>(
+ first1,last1,first2,transparent_equal_to{});
+}
+
+template<
+ typename... Ts,typename Iterator,
+ typename ForwardIterator,typename BinaryPredicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+bool is_permutation(
+ Iterator first1,Iterator last1,
+ ForwardIterator first2,ForwardIterator last2,BinaryPredicate pred)
+{
+ std::tie(first1,first2)=algorithm::mismatch<Ts...>(
+ first1,last1,first2,last2,pred);
+ if(std::distance(first1,last1)!=std::distance(first2,last2))return false;
+ else return is_permutation_suffix<Ts...>(first1,last1,first2,last2,pred);
+}
+
+template<
+ typename... Ts,typename Iterator,typename ForwardIterator,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+bool is_permutation(
+ const Iterator& first1,const Iterator& last1,
+ ForwardIterator first2,ForwardIterator last2)
+{
+ return algorithm::is_permutation<Ts...>(
+ first1,last1,first2,last2,transparent_equal_to{});
+}
+
+template<
+ typename... Ts,typename Iterator,
+ typename ForwardIterator,typename BinaryPredicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+Iterator search(
+ const Iterator& first1,const Iterator& last1,
+ ForwardIterator first2,ForwardIterator last2,BinaryPredicate pred)
+{
+ using traits=iterator_traits<Iterator>;
+
+ auto send=traits::end_base_segment_info_iterator_from(last1);
+ for(auto i:detail::segment_split(first1,last1)){
+ for(auto lbit=i.begin(),lbend=i.end();lbit!=lbend;++lbit){
+ Iterator it=traits::iterator_from(lbit,send);
+ if(algorithm::mismatch<Ts...>(it,last1,first2,last2,pred).second==last2)
+ return it;
+ }
+ }
+ return last1;
+}
+
+template<
+ typename... Ts,typename Iterator,typename ForwardIterator,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+Iterator search(
+ const Iterator& first1,const Iterator& last1,
+ ForwardIterator first2,ForwardIterator last2)
+{
+ return algorithm::search<Ts...>(
+ first1,last1,first2,last2,transparent_equal_to{});
+}
+
+template<
+ typename... Ts,typename Iterator,
+ typename ForwardIterator,typename BinaryPredicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+Iterator find_end(
+ Iterator first1,Iterator last1,
+ ForwardIterator first2,ForwardIterator last2,BinaryPredicate pred)
+{
+ if(first2==last2)return last1;
+
+ for(Iterator res=last1;;){
+ Iterator res1=algorithm::search<Ts...>(first1,last1,first2,last2,pred);
+ if(res1==last1)return res;
+ else{
+ first1=res=res1;
+ ++first1;
+ }
+ }
+}
+
+template<
+ typename... Ts,typename Iterator,typename ForwardIterator,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+Iterator find_end(
+ const Iterator& first1,const Iterator& last1,
+ ForwardIterator first2,ForwardIterator last2)
+{
+ return algorithm::find_end<Ts...>(
+ first1,last1,first2,last2,transparent_equal_to{});
+}
+
+struct search_n_alg
+{
+ template<
+ typename ForwardIterator,typename Size,
+ typename T,typename BinaryPredicate
+ >
+ ForwardIterator operator()(
+ ForwardIterator first,ForwardIterator last,
+ Size count,bool& carry,Size& remain,const T& x, /* note the &s */
+ BinaryPredicate pred)const
+ {
+ for(;first!=last;++first){
+ if(!pred(*first,x)){carry=false;remain=count;continue;}
+ auto res=first;
+ for(;;){
+ if(--remain==0||++first==last)return res;
+ if(!pred(*first,x)){carry=false;remain=count;break;}
+ }
+ }
+ return last;
+ }
+};
+
+template<
+ typename... Ts,typename Iterator,
+ typename Size,typename T,typename BinaryPredicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+Iterator search_n(
+ const Iterator& first,const Iterator& last,
+ Size count,const T& x,BinaryPredicate pred)
+{
+ using traits=iterator_traits<Iterator>;
+ using local_base_iterator=typename traits::local_base_iterator;
+
+ if(count<=0)return first;
+
+ bool carry=false;
+ auto remain=count;
+ auto alg=restitute_range<Ts...>(
+ cast_return<local_base_iterator>(search_n_alg{}),
+ count,carry,remain,x,pred);
+ local_base_iterator prev;
+ for(auto i:detail::segment_split(first,last)){
+ auto it=alg(i);
+ if(it!=i.end()){
+ if(remain==0)
+ return traits::iterator_from(
+ carry?prev:it,
+ traits::end_base_segment_info_iterator_from(last));
+ else if(!carry){prev=it;carry=true;}
+ }
+ }
+ return last;
+}
+
+template<
+ typename... Ts,typename Iterator,
+ typename Size,typename T,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+Iterator search_n(
+ const Iterator& first,const Iterator& last,Size count,const T& x)
+{
+ return algorithm::search_n<Ts...>(
+ first,last,count,x,transparent_equal_to{});
+}
+
+template<
+ typename Algorithm,typename... Ts,
+ typename Iterator,typename OutputIterator,typename... Args,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+OutputIterator generic_copy(
+ const Iterator& first,const Iterator& last,OutputIterator res,Args&&... args)
+{
+ for(auto i:detail::segment_split(first,last)){
+ auto alg=restitute_range<Ts...>(
+ Algorithm{},res,std::forward<Args>(args)...);
+ res=alg(i);
+ }
+ return res;
+}
+
+BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_copy,std::copy)
+
+template<
+ typename... Ts,typename Iterator,typename OutputIterator,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+OutputIterator copy(
+ const Iterator& first,const Iterator& last,OutputIterator res)
+{
+ return generic_copy<std_copy,Ts...>(first,last,res);
+}
+
+BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_copy_n,std::copy_n)
+
+template<
+ typename... Ts,typename Iterator,typename Size,typename OutputIterator,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+OutputIterator copy_n(const Iterator& first,Size count,OutputIterator res)
+{
+ using traits=iterator_traits<Iterator>;
+
+ if(count<=0)return res;
+
+ auto lbit=traits::local_base_iterator_from(first);
+ auto sit=traits::base_segment_info_iterator_from(first);
+ for(;;){
+ auto n=(std::min)(count,sit->end()-lbit);
+ auto alg=restitute_iterator<Ts...>(std_copy_n{},n,res);
+ res=alg(sit->type_info(),lbit);
+ if((count-=n)==0)break;
+ ++sit;
+ lbit=sit->begin();
+ }
+ return res;
+}
+
+BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_copy_if,std::copy_if)
+
+template<
+ typename... Ts,typename Iterator,typename OutputIterator,typename Predicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+OutputIterator copy_if(
+ const Iterator& first,const Iterator& last,OutputIterator res,Predicate pred)
+{
+ return generic_copy<std_copy_if,Ts...>(first,last,res,pred);
+}
+
+BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_move,std::move)
+
+template<
+ typename... Ts,typename Iterator,typename OutputIterator,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+OutputIterator move(
+ const Iterator& first,const Iterator& last,OutputIterator res)
+{
+ return generic_copy<std_move,Ts...>(first,last,res);
+}
+
+BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_transform,std::transform)
+
+template<
+ typename... Ts,typename Iterator,
+ typename OutputIterator,typename UnaryOperation,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+OutputIterator transform(
+ const Iterator& first,const Iterator& last,
+ OutputIterator res,UnaryOperation op)
+{
+ return generic_copy<std_transform,Ts...>(first,last,res,op);
+}
+
+struct transform2_alg
+{
+ template<
+ typename InputIterator1,typename InputIterator2,
+ typename OutputIterator,typename BinaryOperation
+ >
+ OutputIterator operator()(
+ InputIterator1 first1,InputIterator1 last1,
+ OutputIterator res, /* third place for compatibility with generic_copy */
+ InputIterator2& first2, BinaryOperation op)const /* note the & */
+ {
+ while(first1!=last1)*res++=op(*first1++,*first2++);
+ return res;
+ }
+};
+
+template<
+ typename... Ts,typename Iterator,typename InputIterator,
+ typename OutputIterator,typename BinaryOperation,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+OutputIterator transform(
+ const Iterator& first1,const Iterator& last1,InputIterator first2,
+ OutputIterator res,BinaryOperation op)
+{
+ return generic_copy<transform2_alg,Ts...>(first1,last1,res,first2,op);
+}
+
+struct replace_copy_alg
+{
+ /* std::replace_copy broken in VS2015, internal ticket VSO#279818
+ * "<algorithm>: replace_copy() and replace_copy_if() shouldn't use the
+ * conditional operator".
+ */
+
+ template<typename InputIterator,typename OutputIterator,typename T>
+ OutputIterator operator()(
+ InputIterator first,InputIterator last,OutputIterator res,
+ const T& old_x,const T& new_x)
+ {
+ for(;first!=last;++first,++res){
+ if(*first==old_x)*res=new_x;
+ else *res=*first;
+ }
+ return res;
+ }
+};
+
+template<
+ typename... Ts,typename Iterator,typename OutputIterator,typename T,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+OutputIterator replace_copy(
+ const Iterator& first,const Iterator& last,OutputIterator res,
+ const T& old_x,const T& new_x)
+{
+ return generic_copy<replace_copy_alg,Ts...>(first,last,res,old_x,new_x);
+}
+
+struct replace_copy_if_alg
+{
+ /* std::replace_copy_if broken in VS2015, internal ticket VSO#279818
+ * "<algorithm>: replace_copy() and replace_copy_if() shouldn't use the
+ * conditional operator".
+ */
+
+ template<
+ typename InputIterator,typename OutputIterator,
+ typename Predicate,typename T
+ >
+ OutputIterator operator()(
+ InputIterator first,InputIterator last,OutputIterator res,
+ Predicate pred,const T& new_x)
+ {
+ for(;first!=last;++first,++res){
+ if(pred(*first))*res=new_x;
+ else *res=*first;
+ }
+ return res;
+ }
+};
+
+template<
+ typename... Ts,typename Iterator,typename OutputIterator,
+ typename Predicate,typename T,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+OutputIterator replace_copy_if(
+ const Iterator& first,const Iterator& last,OutputIterator res,
+ Predicate pred,const T& new_x)
+{
+ return generic_copy<replace_copy_if_alg,Ts...>(first,last,res,pred,new_x);
+}
+
+BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_remove_copy,std::remove_copy)
+
+template<
+ typename... Ts,typename Iterator,typename OutputIterator,typename T,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+OutputIterator remove_copy(
+ const Iterator& first,const Iterator& last,OutputIterator res,const T& x)
+{
+ return generic_copy<std_remove_copy,Ts...>(first,last,res,x);
+}
+
+BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(
+ std_remove_copy_if,std::remove_copy_if)
+
+template<
+ typename... Ts,typename Iterator,typename OutputIterator,typename Predicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+OutputIterator remove_copy_if(
+ const Iterator& first,const Iterator& last,OutputIterator res,Predicate pred)
+{
+ return generic_copy<std_remove_copy_if,Ts...>(first,last,res,pred);
+}
+
+template<typename... Ts>
+struct unique_copy_alg
+{
+ template<
+ typename LocalIterator,typename OutputIterator,
+ typename BinaryPredicate,typename LocalBaseIterator
+ >
+ OutputIterator operator()(
+ LocalIterator first,LocalIterator last,
+ OutputIterator res, BinaryPredicate pred,
+ bool& carry,const std::type_info* prev_info, /* note the &s */
+ LocalBaseIterator& prev)const
+ {
+ if(carry){
+ auto p=restitute_iterator<Ts...>(deref_to(pred));
+ for(;first!=last;++first)if(!p(*prev_info,prev,first))break;
+ }
+ if(first==last)return res;
+ res=std::unique_copy(first,last,res,pred);
+ carry=true;
+ prev_info=&typeid(
+ typename std::iterator_traits<LocalIterator>::value_type);
+ prev=LocalBaseIterator{last-1};
+ return res;
+ }
+};
+
+template<
+ typename... Ts,typename Iterator,
+ typename OutputIterator,typename BinaryPredicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+OutputIterator unique_copy(
+ const Iterator& first,const Iterator& last,
+ OutputIterator res,BinaryPredicate pred)
+{
+ using traits=iterator_traits<Iterator>;
+ using local_base_iterator=typename traits::local_base_iterator;
+
+ bool carry=false;
+ const std::type_info* prev_info{&typeid(void)};
+ local_base_iterator prev;
+ return generic_copy<unique_copy_alg<Ts...>,Ts...>(
+ first,last,res,pred,carry,prev_info,prev);
+}
+
+template<
+ typename... Ts,typename Iterator,typename OutputIterator,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+OutputIterator unique_copy(
+ const Iterator& first,const Iterator& last,OutputIterator res)
+{
+ return algorithm::unique_copy<Ts...>(first,last,res,transparent_equal_to{});
+}
+
+template<
+ typename... Ts,typename Iterator,typename OutputIterator,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+OutputIterator rotate_copy(
+ const Iterator& first,const Iterator& middle,const Iterator& last,
+ OutputIterator res)
+{
+ res=algorithm::copy<Ts...>(middle,last,res);
+ return algorithm::copy<Ts...>(first,middle,res);
+}
+
+template<
+ typename... Ts,typename Iterator,typename Predicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+bool is_partitioned(const Iterator& first,const Iterator& last,Predicate pred)
+{
+ auto it=algorithm::find_if_not<Ts...>(first,last,pred);
+ if(it==last)return true;
+ return algorithm::none_of<Ts...>(++it,last,pred);
+}
+
+BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(
+ std_partition_copy,std::partition_copy)
+
+template<
+ typename... Ts,typename Iterator,
+ typename OutputIterator1,typename OutputIterator2,typename Predicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+std::pair<OutputIterator1,OutputIterator2> partition_copy(
+ const Iterator& first,const Iterator& last,
+ OutputIterator1 rest,OutputIterator2 resf,Predicate pred)
+{
+ for(auto i:detail::segment_split(first,last)){
+ auto alg=restitute_range<Ts...>(std_partition_copy{},rest,resf,pred);
+ std::tie(rest,resf)=alg(i);
+ }
+ return {rest,resf};
+}
+
+template<typename Predicate,typename... Ts>
+struct partition_point_pred
+{
+ template<typename Iterator>
+ bool operator()(const Iterator& it)const
+ {
+ using traits=iterator_traits<Iterator>;
+ auto p=restitute_iterator<Ts...>(deref_to(pred));
+ return p(
+ traits::base_segment_info_iterator_from(it)->type_info(),
+ traits::local_base_iterator_from(it));
+ }
+
+ Predicate pred;
+};
+
+template<
+ typename... Ts,typename Iterator,typename Predicate,
+ enable_if_poly_collection_iterator<Iterator> =nullptr
+>
+Iterator partition_point(
+ const Iterator& first,const Iterator& last,Predicate pred)
+{
+ auto_iterator<Iterator> afirst{first},alast{last};
+ partition_point_pred<Predicate,Ts...> p{pred};
+ return *std::partition_point(afirst,alast,p);
+}
+
+} /* namespace poly_collection::detail::algorithm */
+
+} /* namespace poly_collection::detail */
+
+/* non-modifying sequence operations */
+
+using detail::algorithm::all_of;
+using detail::algorithm::any_of;
+using detail::algorithm::none_of;
+using detail::algorithm::for_each;
+using detail::algorithm::find;
+using detail::algorithm::find_if;
+using detail::algorithm::find_if_not;
+using detail::algorithm::find_end;
+using detail::algorithm::find_first_of;
+using detail::algorithm::adjacent_find;
+using detail::algorithm::count;
+using detail::algorithm::count_if;
+using detail::algorithm::mismatch;
+using detail::algorithm::equal;
+using detail::algorithm::is_permutation;
+using detail::algorithm::search;
+using detail::algorithm::search_n;
+
+/* modifying sequence operations */
+
+using detail::algorithm::copy;
+using detail::algorithm::copy_n;
+using detail::algorithm::copy_if;
+ /* copy_backwards requires BidirectionalIterator */
+using detail::algorithm::move;
+ /* move_backwards requires BidirectionalIterator */
+ /* swap_ranges requires Swappable */
+ /* iter_swap requires Swappable */
+using detail::algorithm::transform;
+ /* replace requires Assignable */
+ /* replace_if requires Assignable */
+using detail::algorithm::replace_copy;
+using detail::algorithm::replace_copy_if;
+ /* fill requires Assignable */
+ /* fill_n requires Assignable */
+ /* generate requires Assignable */
+ /* generate_n requires Assignable */
+ /* remove requires MoveAssignable */
+ /* remove_if requires MoveAssignable */
+using detail::algorithm::remove_copy;
+using detail::algorithm::remove_copy_if;
+ /* unique requires MoveAssignable */
+using detail::algorithm::unique_copy;
+ /* reverse requires BidirectionalIterator */
+ /* reverse_copy requires BidirectionalIterator */
+ /* rotate requires MoveAssignable */
+using detail::algorithm::rotate_copy;
+ /* shuffle requires RandomAccessIterator */
+using detail::algorithm::is_partitioned;
+ /* partition requires Swappable */
+ /* stable_partition requires Swappable */
+using detail::algorithm::partition_copy;
+using detail::algorithm::partition_point;
+
+/* sorting and related operations not provided */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/any_collection.hpp b/boost/poly_collection/any_collection.hpp
new file mode 100644
index 0000000000..8f9f3739af
--- /dev/null
+++ b/boost/poly_collection/any_collection.hpp
@@ -0,0 +1,80 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_ANY_COLLECTION_HPP
+#define BOOST_POLY_COLLECTION_ANY_COLLECTION_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/poly_collection/any_collection_fwd.hpp>
+#include <boost/poly_collection/detail/any_model.hpp>
+#include <boost/poly_collection/detail/poly_collection.hpp>
+#include <utility>
+
+namespace boost{
+
+namespace poly_collection{
+
+template<typename Concept,typename Allocator>
+class any_collection:
+ public detail::poly_collection_impl::poly_collection<
+ detail::any_model<Concept>,Allocator
+ >
+{
+ using base_type=detail::poly_collection_impl::poly_collection<
+ detail::any_model<Concept>,Allocator>;
+
+ base_type& base()noexcept{return *this;}
+ const base_type& base()const noexcept{return *this;}
+
+public:
+ using base_type::base_type;
+
+ any_collection()=default;
+ any_collection(const any_collection& x)=default;
+ any_collection(any_collection&& x)=default;
+ any_collection& operator=(const any_collection& x)=default;
+ any_collection& operator=(any_collection&& x)=default;
+
+ template<typename C,typename A>
+ friend bool operator==(
+ const any_collection<C,A>&,const any_collection<C,A>&);
+};
+
+template<typename Concept,typename Allocator>
+bool operator==(
+ const any_collection<Concept,Allocator>& x,
+ const any_collection<Concept,Allocator>& y)
+{
+ return x.base()==y.base();
+}
+
+template<typename Concept,typename Allocator>
+bool operator!=(
+ const any_collection<Concept,Allocator>& x,
+ const any_collection<Concept,Allocator>& y)
+{
+ return !(x==y);
+}
+
+template<typename Concept,typename Allocator>
+void swap(
+ any_collection<Concept,Allocator>& x,any_collection<Concept,Allocator>& y)
+{
+ x.swap(y);
+}
+
+} /* namespace */
+
+using poly_collection::any_collection;
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/any_collection_fwd.hpp b/boost/poly_collection/any_collection_fwd.hpp
new file mode 100644
index 0000000000..e457035432
--- /dev/null
+++ b/boost/poly_collection/any_collection_fwd.hpp
@@ -0,0 +1,56 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_ANY_COLLECTION_FWD_HPP
+#define BOOST_POLY_COLLECTION_ANY_COLLECTION_FWD_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <memory>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+template<typename Concept> struct any_model;
+}
+
+template<typename Concept>
+using any_collection_value_type=
+ typename detail::any_model<Concept>::value_type;
+
+template<
+ typename Concept,
+ typename Allocator=std::allocator<any_collection_value_type<Concept>>
+>
+class any_collection;
+
+template<typename Concept,typename Allocator>
+bool operator==(
+ const any_collection<Concept,Allocator>& x,
+ const any_collection<Concept,Allocator>& y);
+
+template<typename Concept,typename Allocator>
+bool operator!=(
+ const any_collection<Concept,Allocator>& x,
+ const any_collection<Concept,Allocator>& y);
+
+template<typename Concept,typename Allocator>
+void swap(
+ any_collection<Concept,Allocator>& x,any_collection<Concept,Allocator>& y);
+
+} /* namespace poly_collection */
+
+using poly_collection::any_collection;
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/base_collection.hpp b/boost/poly_collection/base_collection.hpp
new file mode 100644
index 0000000000..e904f9f020
--- /dev/null
+++ b/boost/poly_collection/base_collection.hpp
@@ -0,0 +1,79 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_BASE_COLLECTION_HPP
+#define BOOST_POLY_COLLECTION_BASE_COLLECTION_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/poly_collection/base_collection_fwd.hpp>
+#include <boost/poly_collection/detail/base_model.hpp>
+#include <boost/poly_collection/detail/poly_collection.hpp>
+#include <utility>
+
+namespace boost{
+
+namespace poly_collection{
+
+template<typename Base,typename Allocator>
+class base_collection:
+ public detail::poly_collection_impl::poly_collection<
+ detail::base_model<Base>,Allocator>
+{
+ using base_type=detail::poly_collection_impl::poly_collection<
+ detail::base_model<Base>,Allocator>;
+
+ base_type& base()noexcept{return *this;}
+ const base_type& base()const noexcept{return *this;}
+
+public:
+ using base_type::base_type;
+
+ base_collection()=default;
+ base_collection(const base_collection& x)=default;
+ base_collection(base_collection&& x)=default;
+ base_collection& operator=(const base_collection& x)=default;
+ base_collection& operator=(base_collection&& x)=default;
+
+ template<typename B,typename A>
+ friend bool operator==(
+ const base_collection<B,A>&,const base_collection<B,A>&);
+};
+
+template<typename Base,typename Allocator>
+bool operator==(
+ const base_collection<Base,Allocator>& x,
+ const base_collection<Base,Allocator>& y)
+{
+ return x.base()==y.base();
+}
+
+template<typename Base,typename Allocator>
+bool operator!=(
+ const base_collection<Base,Allocator>& x,
+ const base_collection<Base,Allocator>& y)
+{
+ return !(x==y);
+}
+
+template<typename Base,typename Allocator>
+void swap(
+ base_collection<Base,Allocator>& x,base_collection<Base,Allocator>& y)
+{
+ x.swap(y);
+}
+
+} /* namespace */
+
+using poly_collection::base_collection;
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/base_collection_fwd.hpp b/boost/poly_collection/base_collection_fwd.hpp
new file mode 100644
index 0000000000..ef4efab1dc
--- /dev/null
+++ b/boost/poly_collection/base_collection_fwd.hpp
@@ -0,0 +1,45 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_BASE_COLLECTION_FWD_HPP
+#define BOOST_POLY_COLLECTION_BASE_COLLECTION_FWD_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <memory>
+
+namespace boost{
+
+namespace poly_collection{
+
+template<typename Base,typename Allocator=std::allocator<Base>>
+class base_collection;
+
+template<typename Base,typename Allocator>
+bool operator==(
+ const base_collection<Base,Allocator>& x,
+ const base_collection<Base,Allocator>& y);
+
+template<typename Base,typename Allocator>
+bool operator!=(
+ const base_collection<Base,Allocator>& x,
+ const base_collection<Base,Allocator>& y);
+
+template<typename Base,typename Allocator>
+void swap(
+ base_collection<Base,Allocator>& x,base_collection<Base,Allocator>& y);
+
+} /* namespace poly_collection */
+
+using poly_collection::base_collection;
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/any_iterator.hpp b/boost/poly_collection/detail/any_iterator.hpp
new file mode 100644
index 0000000000..a51ae86b61
--- /dev/null
+++ b/boost/poly_collection/detail/any_iterator.hpp
@@ -0,0 +1,92 @@
+/* Copyright 2016 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_ANY_ITERATOR_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_ANY_ITERATOR_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/type_erasure/any_cast.hpp>
+#include <type_traits>
+#include <utility>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* type_erasure::any<Concept>* adaptor convertible to pointer to wrapped
+ * entity.
+ */
+
+template<typename Any>
+class any_iterator:public boost::iterator_adaptor<any_iterator<Any>,Any*>
+{
+public:
+ any_iterator()=default;
+ explicit any_iterator(Any* p)noexcept:any_iterator::iterator_adaptor_{p}{}
+ any_iterator(const any_iterator&)=default;
+ any_iterator& operator=(const any_iterator&)=default;
+
+ template<
+ typename NonConstAny,
+ typename std::enable_if<
+ std::is_same<Any,const NonConstAny>::value>::type* =nullptr
+ >
+ any_iterator(const any_iterator<NonConstAny>& x)noexcept:
+ any_iterator::iterator_adaptor_{x.base()}{}
+
+ template<
+ typename NonConstAny,
+ typename std::enable_if<
+ std::is_same<Any,const NonConstAny>::value>::type* =nullptr
+ >
+ any_iterator& operator=(const any_iterator<NonConstAny>& x)noexcept
+ {
+ this->base_reference()=x.base();
+ return *this;
+ }
+
+ /* interoperability with Any* */
+
+ any_iterator& operator=(Any* p)noexcept
+ {this->base_reference()=p;return *this;}
+ operator Any*()const noexcept{return this->base();}
+
+ /* interoperability with Concrete* */
+
+ template<
+ typename Concrete,
+ typename std::enable_if<
+ /* can't compile-time check concept compliance */
+ !std::is_const<Any>::value||std::is_const<Concrete>::value
+ >::type* =nullptr
+ >
+ explicit operator Concrete*()const noexcept
+ {
+ return const_cast<Concrete*>(
+ static_cast<typename std::remove_const<Concrete>::type*>(
+ type_erasure::any_cast<void*>(this->base())));
+ }
+
+private:
+ template<typename>
+ friend class any_iterator;
+};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/any_model.hpp b/boost/poly_collection/detail/any_model.hpp
new file mode 100644
index 0000000000..d38bf0e4a3
--- /dev/null
+++ b/boost/poly_collection/detail/any_model.hpp
@@ -0,0 +1,214 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_ANY_MODEL_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_ANY_MODEL_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/core/addressof.hpp>
+#include <boost/mpl/map/map10.hpp>
+#include <boost/mpl/pair.hpp>
+#include <boost/mpl/vector/vector10.hpp>
+#include <boost/poly_collection/detail/any_iterator.hpp>
+#include <boost/poly_collection/detail/is_acceptable.hpp>
+#include <boost/poly_collection/detail/segment_backend.hpp>
+#include <boost/poly_collection/detail/split_segment.hpp>
+#include <boost/type_erasure/any.hpp>
+#include <boost/type_erasure/any_cast.hpp>
+#include <boost/type_erasure/binding.hpp>
+#include <boost/type_erasure/builtin.hpp>
+#include <boost/type_erasure/concept_of.hpp>
+#include <boost/type_erasure/is_subconcept.hpp>
+#include <boost/type_erasure/relaxed.hpp>
+#include <boost/type_erasure/static_binding.hpp>
+#include <boost/type_erasure/typeid_of.hpp>
+#include <memory>
+#include <type_traits>
+#include <typeinfo>
+#include <utility>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* model for any_collection */
+
+template<typename Concept>
+struct any_model;
+
+/* Refine is_acceptable to cover type_erasure::any classes whose assignment
+ * operator won't compile.
+ */
+
+template<typename Concept,typename Concept2,typename T>
+struct is_acceptable<
+ type_erasure::any<Concept2,T>,any_model<Concept>,
+ typename std::enable_if<
+ !type_erasure::is_relaxed<Concept2>::value&&
+ !type_erasure::is_subconcept<type_erasure::assignable<>,Concept2>::value&&
+ !type_erasure::is_subconcept<
+ type_erasure::assignable<type_erasure::_self,type_erasure::_self&&>,
+ Concept2>::value
+ >::type
+>:std::false_type{};
+
+/* is_terminal defined out-class to allow for partial specialization */
+
+template<typename Concept,typename T>
+using any_model_enable_if_has_typeid_=typename std::enable_if<
+ type_erasure::is_subconcept<
+ type_erasure::typeid_<typename std::decay<T>::type>,
+ Concept
+ >::value
+>::type*;
+
+template<typename T,typename=void*>
+struct any_model_is_terminal:std::true_type{};
+
+template<typename Concept,typename T>
+struct any_model_is_terminal<
+ type_erasure::any<Concept,T>,any_model_enable_if_has_typeid_<Concept,T>
+>:std::false_type{};
+
+/* used for make_value_type */
+
+template<typename T,typename Q>
+struct any_model_make_reference
+{
+ static T& apply(Q& x){return x;}
+};
+
+template<typename Concept>
+struct any_model
+{
+ using value_type=type_erasure::any<
+ typename std::conditional<
+ type_erasure::is_subconcept<type_erasure::typeid_<>,Concept>::value,
+ Concept,
+ mpl::vector2<Concept,type_erasure::typeid_<>>
+ >::type,
+ type_erasure::_self&
+ >;
+
+ template<typename Concrete>
+ using is_subtype=std::true_type; /* can't compile-time check concept
+ * compliance */
+ template<typename T>
+ using is_terminal=any_model_is_terminal<T>;
+
+ template<typename T>
+ static const std::type_info& subtypeid(const T&){return typeid(T);}
+
+ template<
+ typename Concept2,typename T,
+ any_model_enable_if_has_typeid_<Concept2,T> =nullptr
+ >
+ static const std::type_info& subtypeid(
+ const type_erasure::any<Concept2,T>& a)
+ {
+ return type_erasure::typeid_of(a);
+ }
+
+ template<typename T>
+ static void* subaddress(T& x){return boost::addressof(x);}
+
+ template<typename T>
+ static const void* subaddress(const T& x){return boost::addressof(x);}
+
+ template<
+ typename Concept2,typename T,
+ any_model_enable_if_has_typeid_<Concept2,T> =nullptr
+ >
+ static void* subaddress(type_erasure::any<Concept2,T>& a)
+ {
+ return type_erasure::any_cast<void*>(&a);
+ }
+
+ template<
+ typename Concept2,typename T,
+ any_model_enable_if_has_typeid_<Concept2,T> =nullptr
+ >
+ static const void* subaddress(const type_erasure::any<Concept2,T>& a)
+ {
+ return type_erasure::any_cast<const void*>(&a);
+ }
+
+ using base_iterator=any_iterator<value_type>;
+ using const_base_iterator=any_iterator<const value_type>;
+ using base_sentinel=value_type*;
+ using const_base_sentinel=const value_type*;
+ template<typename Concrete>
+ using iterator=Concrete*;
+ template<typename Concrete>
+ using const_iterator=const Concrete*;
+ using segment_backend=detail::segment_backend<any_model>;
+ template<typename Concrete,typename Allocator>
+ using segment_backend_implementation=split_segment<
+ any_model,
+ Concrete,
+ typename std::allocator_traits<Allocator>::
+ template rebind_alloc<Concrete>
+ >;
+ using segment_backend_unique_ptr=
+ typename segment_backend::segment_backend_unique_ptr;
+
+ static base_iterator nonconst_iterator(const_base_iterator it)
+ {
+ return base_iterator{
+ const_cast<value_type*>(static_cast<const value_type*>(it))};
+ }
+
+ template<typename T>
+ static iterator<T> nonconst_iterator(const_iterator<T> it)
+ {
+ return const_cast<iterator<T>>(it);
+ }
+
+ template<typename Concrete,typename Allocator>
+ static segment_backend_unique_ptr make(const Allocator& al)
+ {
+ return segment_backend_implementation<Concrete,Allocator>::new_(al,al);
+ }
+
+private:
+ template<typename,typename,typename>
+ friend class split_segment;
+
+ template<typename Concrete>
+ static value_type make_value_type(Concrete& x){return value_type{x};}
+
+ template<typename Concept2,typename T>
+ static value_type make_value_type(type_erasure::any<Concept2,T>& x)
+ {
+ /* I don't pretend to understand what's going on here, see
+ * https://lists.boost.org/boost-users/2017/05/87556.php
+ */
+
+ using namespace boost::type_erasure;
+ using ref_type=any<Concept2,T>;
+ using make_ref=any_model_make_reference<_self,ref_type>;
+ using concept_=typename concept_of<value_type>::type;
+
+ auto b=make_binding<mpl::map1<mpl::pair<_self,ref_type>>>();
+
+ return {call(binding<make_ref>{b},make_ref{},x),binding<concept_>{b}};
+ }
+};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/auto_iterator.hpp b/boost/poly_collection/detail/auto_iterator.hpp
new file mode 100644
index 0000000000..397329b91b
--- /dev/null
+++ b/boost/poly_collection/detail/auto_iterator.hpp
@@ -0,0 +1,56 @@
+/* Copyright 2016 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_AUTO_ITERATOR_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_AUTO_ITERATOR_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/iterator/iterator_adaptor.hpp>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* auto_iterator<Iterator> (for want of a better name) behaves like Iterator
+ * save for the fact that it derefs to Iterator& rather than
+ * Iterator::reference. This is useful to "lift" std algorithms so that
+ * user-defined predicates are passed iterators that can then be dereferenced
+ * internally.
+ */
+
+template<typename Iterator>
+class auto_iterator:
+ public boost::iterator_adaptor<auto_iterator<Iterator>,Iterator,Iterator>
+{
+public:
+ auto_iterator()=default;
+ auto_iterator(const Iterator& it):auto_iterator::iterator_adaptor_{it}{}
+ auto_iterator(const auto_iterator&)=default;
+ auto_iterator& operator=(const auto_iterator&)=default;
+
+private:
+ friend class boost::iterator_core_access;
+
+ Iterator& dereference()const noexcept
+ {
+ return const_cast<auto_iterator*>(this)->base_reference();
+ }
+};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/base_model.hpp b/boost/poly_collection/detail/base_model.hpp
new file mode 100644
index 0000000000..db6126d2e3
--- /dev/null
+++ b/boost/poly_collection/detail/base_model.hpp
@@ -0,0 +1,130 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_BASE_MODEL_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_BASE_MODEL_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/core/addressof.hpp>
+#include <boost/poly_collection/detail/is_final.hpp>
+#include <boost/poly_collection/detail/packed_segment.hpp>
+#include <boost/poly_collection/detail/stride_iterator.hpp>
+#include <memory>
+#include <type_traits>
+#include <typeinfo>
+#include <utility>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* model for base_collection */
+
+template<typename Base>
+struct base_model
+{
+ using value_type=Base;
+ template<typename Derived>
+ using is_subtype=std::is_base_of<Base,Derived>;
+ template<typename T>
+ using is_terminal=is_final<T>; //TODO: should we say !is_polymorhpic||is_final?
+
+private:
+ template<typename T>
+ using enable_if_not_terminal=
+ typename std::enable_if<!is_terminal<T>::value>::type*;
+ template<typename T>
+ using enable_if_terminal=
+ typename std::enable_if<is_terminal<T>::value>::type*;
+
+public:
+ template<typename T,enable_if_not_terminal<T> =nullptr>
+ static const std::type_info& subtypeid(const T& x){return typeid(x);}
+
+ template<typename T,enable_if_terminal<T> =nullptr>
+ static const std::type_info& subtypeid(const T&){return typeid(T);}
+
+ template<typename T,enable_if_not_terminal<T> =nullptr>
+ static void* subaddress(T& x)
+ {
+ return dynamic_cast<void*>(boost::addressof(x));
+ }
+
+ template<typename T,enable_if_not_terminal<T> =nullptr>
+ static const void* subaddress(const T& x)
+ {
+ return dynamic_cast<const void*>(boost::addressof(x));
+ }
+
+ template<typename T,enable_if_terminal<T> =nullptr>
+ static void* subaddress(T& x){return boost::addressof(x);}
+
+ template<typename T,enable_if_terminal<T> =nullptr>
+ static const void* subaddress(const T& x){return boost::addressof(x);}
+
+ using base_iterator=stride_iterator<Base>;
+ using const_base_iterator=stride_iterator<const Base>;
+ using base_sentinel=Base*;
+ using const_base_sentinel=const Base*;
+ template<typename Derived>
+ using iterator=Derived*;
+ template<typename Derived>
+ using const_iterator=const Derived*;
+ using segment_backend=detail::segment_backend<base_model>;
+ template<typename Derived,typename Allocator>
+ using segment_backend_implementation=packed_segment<
+ base_model,
+ Derived,
+ typename std::allocator_traits<Allocator>::template rebind_alloc<Derived>
+ >;
+ using segment_backend_unique_ptr=
+ typename segment_backend::segment_backend_unique_ptr;
+
+ static base_iterator nonconst_iterator(const_base_iterator it)
+ {
+ return {
+ const_cast<value_type*>(static_cast<const value_type*>(it)),
+ it.stride()
+ };
+ }
+
+ template<typename T>
+ static iterator<T> nonconst_iterator(const_iterator<T> it)
+ {
+ return const_cast<iterator<T>>(it);
+ }
+
+ template<typename Derived,typename Allocator>
+ static segment_backend_unique_ptr make(const Allocator& al)
+ {
+ return segment_backend_implementation<Derived,Allocator>::new_(al,al);
+ }
+
+private:
+ template<typename,typename,typename>
+ friend class packed_segment;
+
+ template<typename Derived>
+ static const Base* value_ptr(const Derived* p)noexcept
+ {
+ return p;
+ }
+};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/callable_wrapper.hpp b/boost/poly_collection/detail/callable_wrapper.hpp
new file mode 100644
index 0000000000..9b339db8f2
--- /dev/null
+++ b/boost/poly_collection/detail/callable_wrapper.hpp
@@ -0,0 +1,104 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_CALLABLE_WRAPPER_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_CALLABLE_WRAPPER_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/poly_collection/detail/is_invocable.hpp>
+#include <functional>
+#include <type_traits>
+#include <typeinfo>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* lightweight std::function look-alike over non-owned callable entities */
+
+template<typename Signature>
+class callable_wrapper;
+
+template<typename R,typename... Args>
+class callable_wrapper<R(Args...)>
+{
+public:
+ // TODO: we should prevent assignment by user code
+ template<
+ typename Callable,
+ typename std::enable_if<
+ !std::is_same<Callable,callable_wrapper>::value&&
+ is_invocable_r<R,Callable,Args...>::value
+ >::type* =nullptr
+ >
+ explicit callable_wrapper(Callable& x)noexcept:pt{info(x)},px{&x}{}
+ callable_wrapper(const callable_wrapper&)=default;
+ callable_wrapper& operator=(const callable_wrapper&)=default;
+
+ explicit operator bool()const noexcept{return true;}
+
+ R operator()(Args... args)const
+ {return pt->call(px,std::forward<Args>(args)...);}
+
+ const std::type_info& target_type()const noexcept{return pt->info;}
+
+ template<typename T>
+ T* target()noexcept
+ {return typeid(T)==pt->info?static_cast<T*>(px):nullptr;}
+ template<typename T>
+ const T* target()const noexcept
+ {return typeid(T)==pt->info?static_cast<const T*>(px):nullptr;}
+
+ /* not in std::function interface */
+
+ operator std::function<R(Args...)>()const noexcept{return pt->convert(px);}
+
+ void* data()noexcept{return px;}
+ const void* data()const noexcept{return px;}
+
+private:
+ struct table
+ {
+ R(*call)(void*,Args...);
+ const std::type_info& info;
+ std::function<R(Args...)> (*convert)(void*);
+ };
+
+ template<typename Callable>
+ static table* info(Callable&)noexcept
+ {
+ static table t={
+ [](void* p,Args... args){
+ auto r=std::ref(*static_cast<Callable*>(p));
+ return static_cast<R>(r(std::forward<Args>(args)...));
+ },
+ typeid(Callable),
+ [](void* p){
+ auto r=std::ref(*static_cast<Callable*>(p));
+ return std::function<R(Args...)>{r};
+ }
+ };
+ return &t;
+ }
+
+ table* pt;
+ void* px;
+};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/callable_wrapper_iterator.hpp b/boost/poly_collection/detail/callable_wrapper_iterator.hpp
new file mode 100644
index 0000000000..fb3ca2338d
--- /dev/null
+++ b/boost/poly_collection/detail/callable_wrapper_iterator.hpp
@@ -0,0 +1,95 @@
+/* Copyright 2016 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_CALLABLE_WRAPPER_ITERATOR_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_CALLABLE_WRAPPER_ITERATOR_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <type_traits>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* callable_wrapper<Sig>* adaptor convertible to pointer to wrapped entity */
+
+template<typename CWrapper>
+class callable_wrapper_iterator:public boost::iterator_adaptor<
+ callable_wrapper_iterator<CWrapper>,CWrapper*
+>
+{
+public:
+ callable_wrapper_iterator()=default;
+ explicit callable_wrapper_iterator(CWrapper* p)noexcept:
+ callable_wrapper_iterator::iterator_adaptor_{p}{}
+ callable_wrapper_iterator(const callable_wrapper_iterator&)=default;
+ callable_wrapper_iterator& operator=(
+ const callable_wrapper_iterator&)=default;
+
+ template<
+ typename NonConstCWrapper,
+ typename std::enable_if<
+ std::is_same<CWrapper,const NonConstCWrapper>::value>::type* =nullptr
+ >
+ callable_wrapper_iterator(
+ const callable_wrapper_iterator<NonConstCWrapper>& x)noexcept:
+ callable_wrapper_iterator::iterator_adaptor_{x.base()}{}
+
+ template<
+ typename NonConstCWrapper,
+ typename std::enable_if<
+ std::is_same<CWrapper,const NonConstCWrapper>::value>::type* =nullptr
+ >
+ callable_wrapper_iterator& operator=(
+ const callable_wrapper_iterator<NonConstCWrapper>& x)noexcept
+ {
+ this->base_reference()=x.base();
+ return *this;
+ }
+
+ /* interoperability with CWrapper* */
+
+ callable_wrapper_iterator& operator=(CWrapper* p)noexcept
+ {this->base_reference()=p;return *this;}
+ operator CWrapper*()const noexcept{return this->base();}
+
+ /* interoperability with Callable* */
+
+ template<
+ typename Callable,
+ typename std::enable_if<
+ std::is_constructible<CWrapper,Callable&>::value&&
+ (!std::is_const<CWrapper>::value||std::is_const<Callable>::value)
+ >::type* =nullptr
+ >
+ explicit operator Callable*()const noexcept
+ {
+ return const_cast<Callable*>(
+ static_cast<const Callable*>(
+ const_cast<const void*>(
+ this->base()->data())));
+ }
+
+private:
+ template<typename>
+ friend class callable_wrapper_iterator;
+};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/function_model.hpp b/boost/poly_collection/detail/function_model.hpp
new file mode 100644
index 0000000000..bc2f9b6846
--- /dev/null
+++ b/boost/poly_collection/detail/function_model.hpp
@@ -0,0 +1,137 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_FUNCTION_MODEL_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_FUNCTION_MODEL_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/core/addressof.hpp>
+#include <boost/poly_collection/detail/callable_wrapper.hpp>
+#include <boost/poly_collection/detail/callable_wrapper_iterator.hpp>
+#include <boost/poly_collection/detail/is_invocable.hpp>
+#include <boost/poly_collection/detail/segment_backend.hpp>
+#include <boost/poly_collection/detail/split_segment.hpp>
+#include <memory>
+#include <type_traits>
+#include <typeinfo>
+#include <utility>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* model for function_collection */
+
+template<typename Signature>
+struct function_model;
+
+/* is_terminal defined out-class to allow for partial specialization */
+
+template<typename T>
+struct function_model_is_terminal:std::true_type{};
+
+template<typename Signature>
+struct function_model_is_terminal<callable_wrapper<Signature>>:
+ std::false_type{};
+
+template<typename R,typename... Args>
+struct function_model<R(Args...)>
+{
+ using value_type=callable_wrapper<R(Args...)>;
+
+ template<typename Callable>
+ using is_subtype=is_invocable_r<R,Callable&,Args...>;
+
+ template<typename T>
+ using is_terminal=function_model_is_terminal<T>;
+
+ template<typename T>
+ static const std::type_info& subtypeid(const T&){return typeid(T);}
+
+ template<typename Signature>
+ static const std::type_info& subtypeid(
+ const callable_wrapper<Signature>& f)
+ {
+ return f.target_type();
+ }
+
+ template<typename T>
+ static void* subaddress(T& x){return boost::addressof(x);}
+
+ template<typename T>
+ static const void* subaddress(const T& x){return boost::addressof(x);}
+
+ template<typename Signature>
+ static void* subaddress(callable_wrapper<Signature>& f)
+ {
+ return f.data();
+ }
+
+ template<typename Signature>
+ static const void* subaddress(const callable_wrapper<Signature>& f)
+ {
+ return f.data();
+ }
+
+ using base_iterator=callable_wrapper_iterator<value_type>;
+ using const_base_iterator=callable_wrapper_iterator<const value_type>;
+ using base_sentinel=value_type*;
+ using const_base_sentinel=const value_type*;
+ template<typename Callable>
+ using iterator=Callable*;
+ template<typename Callable>
+ using const_iterator=const Callable*;
+ using segment_backend=detail::segment_backend<function_model>;
+ template<typename Callable,typename Allocator>
+ using segment_backend_implementation=split_segment<
+ function_model,
+ Callable,
+ typename std::allocator_traits<Allocator>::
+ template rebind_alloc<Callable>
+ >;
+ using segment_backend_unique_ptr=
+ typename segment_backend::segment_backend_unique_ptr;
+
+ static base_iterator nonconst_iterator(const_base_iterator it)
+ {
+ return base_iterator{
+ const_cast<value_type*>(static_cast<const value_type*>(it))};
+ }
+
+ template<typename T>
+ static iterator<T> nonconst_iterator(const_iterator<T> it)
+ {
+ return const_cast<iterator<T>>(it);
+ }
+
+ template<typename Callable,typename Allocator>
+ static segment_backend_unique_ptr make(const Allocator& al)
+ {
+ return segment_backend_implementation<Callable,Allocator>::new_(al,al);
+ }
+
+private:
+ template<typename,typename,typename>
+ friend class split_segment;
+
+ template<typename Callable>
+ static value_type make_value_type(Callable& x){return value_type{x};}
+};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/functional.hpp b/boost/poly_collection/detail/functional.hpp
new file mode 100644
index 0000000000..26e1bcb394
--- /dev/null
+++ b/boost/poly_collection/detail/functional.hpp
@@ -0,0 +1,196 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_FUNCTIONAL_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_FUNCTIONAL_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/poly_collection/detail/integer_sequence.hpp>
+#include <tuple>
+#include <utility>
+
+/* Assorted functional utilities. Much of this would be almost trivial with
+ * C++14 generic lambdas.
+ */
+
+#if BOOST_WORKAROUND(BOOST_MSVC,>=1910)
+/* https://lists.boost.org/Archives/boost/2017/06/235687.php */
+
+#define BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(name,f) \
+struct name \
+{ \
+ template<typename... Args> \
+ auto operator()(Args&&... args)const \
+ { \
+ return f(std::forward<Args>(args)...); \
+ } \
+};
+#else
+#define BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(name,f) \
+struct name \
+{ \
+ template<typename... Args> \
+ auto operator()(Args&&... args)const-> \
+ decltype(f(std::forward<Args>(args)...)) \
+ { \
+ return f(std::forward<Args>(args)...); \
+ } \
+};
+#endif
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+template<typename F,typename Tuple>
+struct tail_closure_class
+{
+ template<typename... Args,std::size_t... I>
+ auto call(index_sequence<I...>,Args&&... args)
+ ->decltype(std::declval<F>()(
+ std::forward<Args>(args)...,
+ std::get<I>(std::declval<Tuple>())...))
+ {
+ return f(std::forward<Args>(args)...,std::get<I>(t)...);
+ }
+
+ template<typename... Args>
+ auto operator()(Args&&... args)
+ ->decltype(this->call(
+ make_index_sequence<std::tuple_size<Tuple>::value>{},
+ std::forward<Args>(args)...))
+ {
+ return call(
+ make_index_sequence<std::tuple_size<Tuple>::value>{},
+ std::forward<Args>(args)...);
+ }
+
+ F f;
+ Tuple t;
+};
+
+template<typename F,typename... Args>
+auto tail_closure(const F& f,Args&&... args)
+ ->tail_closure_class<F,std::tuple<Args&&...>>
+{
+ return {f,std::forward_as_tuple(std::forward<Args>(args)...)};
+}
+
+template<typename F,typename Tuple>
+struct head_closure_class
+{
+ template<typename... Args,std::size_t... I>
+ auto call(index_sequence<I...>,Args&&... args)
+ ->decltype(std::declval<F>()(
+ std::get<I>(std::declval<Tuple>())...,std::forward<Args>(args)...))
+ {
+ return f(std::get<I>(t)...,std::forward<Args>(args)...);
+ }
+
+ template<typename... Args>
+ auto operator()(Args&&... args)
+ ->decltype(this->call(
+ make_index_sequence<std::tuple_size<Tuple>::value>{},
+ std::forward<Args>(args)...))
+ {
+ return call(
+ make_index_sequence<std::tuple_size<Tuple>::value>{},
+ std::forward<Args>(args)...);
+ }
+
+ F f;
+ Tuple t;
+};
+
+template<typename F,typename... Args>
+auto head_closure(const F& f,Args&&... args)
+ ->head_closure_class<F,std::tuple<Args&&...>>
+{
+ return {f,std::forward_as_tuple(std::forward<Args>(args)...)};
+}
+
+template<typename ReturnType,typename F>
+struct cast_return_class
+{
+ template<typename... Args>
+ ReturnType operator()(Args&&... args)const
+ {
+ return static_cast<ReturnType>(f(std::forward<Args>(args)...));
+ }
+
+ F f;
+};
+
+template<typename ReturnType,typename F>
+cast_return_class<ReturnType,F> cast_return(const F& f)
+{
+ return {f};
+}
+
+template<typename F>
+struct deref_to_class
+{
+ template<typename... Args>
+ auto operator()(Args&&... args)->decltype(std::declval<F>()(*args...))
+ {
+ return f(*args...);
+ }
+
+ F f;
+};
+
+template<typename F>
+deref_to_class<F> deref_to(const F& f)
+{
+ return {f};
+}
+
+template<typename F>
+struct deref_1st_to_class
+{
+ template<typename Arg,typename... Args>
+ auto operator()(Arg&& arg,Args&&... args)
+ ->decltype(std::declval<F>()(*arg,std::forward<Args>(args)...))
+ {
+ return f(*arg,std::forward<Args>(args)...);
+ }
+
+ F f;
+};
+
+template<typename F>
+deref_1st_to_class<F> deref_1st_to(const F& f)
+{
+ return {f};
+}
+
+struct transparent_equal_to
+{
+ template<typename T,typename U>
+ auto operator()(T&& x,U&& y)const
+ noexcept(noexcept(std::forward<T>(x)==std::forward<U>(y)))
+ ->decltype(std::forward<T>(x)==std::forward<U>(y))
+ {
+ return std::forward<T>(x)==std::forward<U>(y);
+ }
+};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/integer_sequence.hpp b/boost/poly_collection/detail/integer_sequence.hpp
new file mode 100644
index 0000000000..d88e833f99
--- /dev/null
+++ b/boost/poly_collection/detail/integer_sequence.hpp
@@ -0,0 +1,64 @@
+/* Copyright 2016 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_INTEGER_SEQUENCE_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_INTEGER_SEQUENCE_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <cstddef>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* ripped from http://pdimov.com/cpp2/simple_cxx11_metaprogramming.html */
+
+template<typename T,T... Ints> struct integer_sequence{};
+
+template<typename S> struct next_integer_sequence;
+
+template<typename T,T... Ints>
+struct next_integer_sequence<integer_sequence<T,Ints...>>
+{
+ using type=integer_sequence<T,Ints...,sizeof...(Ints)>;
+};
+
+template<typename T,T I,T N> struct make_int_seq_impl;
+
+template<typename T,T N>
+using make_integer_sequence=typename make_int_seq_impl<T,0,N>::type;
+
+template<typename T,T I,T N> struct make_int_seq_impl
+{
+ using type=typename next_integer_sequence<
+ typename make_int_seq_impl<T,I+1,N>::type>::type;
+};
+
+template<typename T,T N> struct make_int_seq_impl<T,N,N>
+{
+ using type=integer_sequence<T>;
+};
+
+template<std::size_t... Ints>
+using index_sequence=integer_sequence<std::size_t,Ints...>;
+
+template<std::size_t N>
+using make_index_sequence=make_integer_sequence<std::size_t,N>;
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/is_acceptable.hpp b/boost/poly_collection/detail/is_acceptable.hpp
new file mode 100644
index 0000000000..c578b8e92e
--- /dev/null
+++ b/boost/poly_collection/detail/is_acceptable.hpp
@@ -0,0 +1,44 @@
+/* Copyright 2016 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_IS_ACCEPTABLE_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_IS_ACCEPTABLE_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <type_traits>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* This can be further specialized by Model when the std type trait classes
+ * fail to give the right info (as it can happen with class templates whose
+ * nominally existing operators do not compile for certain instantiations).
+ */
+
+template<typename T,typename Model,typename=void>
+struct is_acceptable:std::integral_constant<
+ bool,
+ Model::template is_subtype<T>::value&&
+ std::is_move_constructible<typename std::decay<T>::type>::value&&
+ (std::is_move_assignable<typename std::decay<T>::type>::value||
+ std::is_nothrow_move_constructible<typename std::decay<T>::type>::value)
+>{};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/is_constructible.hpp b/boost/poly_collection/detail/is_constructible.hpp
new file mode 100644
index 0000000000..5770fab537
--- /dev/null
+++ b/boost/poly_collection/detail/is_constructible.hpp
@@ -0,0 +1,61 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_IS_CONSTRUCIBLE_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_IS_CONSTRUCIBLE_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+
+#if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1900))
+/* https://connect.microsoft.com/VisualStudio/Feedback/Details/2118677 */
+
+#include <boost/type_traits/is_constructible.hpp>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+template<typename T,typename... Args>
+struct is_constructible:std::integral_constant<
+ bool,
+ boost::is_constructible<T,Args...>::value
+>{};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#else
+#include <type_traits>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+template<typename T,typename... Args>
+using is_constructible=std::is_constructible<T,Args...>;
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
+#endif
diff --git a/boost/poly_collection/detail/is_equality_comparable.hpp b/boost/poly_collection/detail/is_equality_comparable.hpp
new file mode 100644
index 0000000000..898dd55f14
--- /dev/null
+++ b/boost/poly_collection/detail/is_equality_comparable.hpp
@@ -0,0 +1,89 @@
+/* Copyright 2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_IS_EQUALITY_COMPARABLE_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_IS_EQUALITY_COMPARABLE_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/config.hpp>
+#include <type_traits>
+
+#if !defined(BOOST_NO_SFINAE_EXPR)
+#include <utility>
+#else
+#include <boost/poly_collection/detail/is_likely_stateless_lambda.hpp>
+#include <boost/type_traits/has_equal_to.hpp>
+#endif
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+#if !defined(BOOST_NO_SFINAE_EXPR)
+
+/* trivial, expression SFINAE-based implementation */
+
+template<typename T,typename=void>
+struct is_equality_comparable:std::false_type{};
+
+template<typename T>
+struct is_equality_comparable<
+ T,
+ typename std::enable_if<
+ std::is_convertible<
+ decltype(std::declval<T>()==std::declval<T>()),bool
+ >::value
+ >::type
+>:std::true_type{};
+
+#else
+/* boost::has_equal_to does a decent job without using expression SFINAE,
+ * but it produces a compile error when the type T being checked is
+ * convertible to an equality-comparable type Q. Exotic as it may seem,
+ * this is exactly the situation with the very important case of stateless
+ * lambda expressions, which are convertible to an equality-comparable
+ * function pointer with the same signature. We take explicit care of
+ * stateless lambdas then.
+ */
+
+template<typename T,typename=void>
+struct is_equality_comparable:std::integral_constant<
+ bool,
+ has_equal_to<T,T,bool>::value
+>{};
+
+template<typename T>
+struct is_equality_comparable<
+ T,
+ typename std::enable_if<is_likely_stateless_lambda<T>::value>::type
+>:
+#if !defined(BOOST_MSVC)
+ std::true_type{};
+#else
+ /* To complicate things further, in VS stateless lambdas are convertible not
+ * only to regular function pointers, but also to other call conventions
+ * such as __stdcall, __fastcall, etc., which makes equality comparison
+ * ambiguous.
+ */
+
+ std::false_type{};
+#endif
+#endif
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/is_final.hpp b/boost/poly_collection/detail/is_final.hpp
new file mode 100644
index 0000000000..b9d91fcf8f
--- /dev/null
+++ b/boost/poly_collection/detail/is_final.hpp
@@ -0,0 +1,68 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_IS_FINAL_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_IS_FINAL_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/type_traits/is_final.hpp>
+#include <type_traits>
+
+/* technique explained at
+ * http://bannalia.blogspot.com/2016/09/compile-time-checking-existence-of.html
+ */
+
+namespace boost{
+namespace poly_collection{
+namespace detail{
+namespace is_final_fallback{
+
+template<typename T> using is_final=boost::is_final<T>;
+
+struct hook{};
+
+}}}}
+
+namespace std{
+
+template<>
+struct is_void< ::boost::poly_collection::detail::is_final_fallback::hook>:
+ std::false_type
+{
+ template<typename T>
+ static constexpr bool is_final_f()
+ {
+ using namespace ::boost::poly_collection::detail::is_final_fallback;
+ return is_final<T>::value;
+ }
+};
+
+} /* namespace std */
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+template<typename T>
+struct is_final:std::integral_constant<
+ bool,
+ std::is_void<is_final_fallback::hook>::template is_final_f<T>()
+>{};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/is_invocable.hpp b/boost/poly_collection/detail/is_invocable.hpp
new file mode 100644
index 0000000000..c93ba476b7
--- /dev/null
+++ b/boost/poly_collection/detail/is_invocable.hpp
@@ -0,0 +1,97 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_IS_INVOCABLE_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_IS_INVOCABLE_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <functional>
+#include <type_traits>
+
+/* technique explained at
+ * http://bannalia.blogspot.com/2016/09/compile-time-checking-existence-of.html
+ */
+
+namespace boost{
+namespace poly_collection{
+namespace detail{
+namespace is_invocable_fallback{
+
+template <typename F,typename... Args>
+struct is_invocable:
+ std::is_constructible<
+ std::function<void(Args...)>,
+ std::reference_wrapper<typename std::remove_reference<F>::type>
+ >
+{};
+
+template <typename R,typename F,typename... Args>
+struct is_invocable_r:
+ std::is_constructible<
+ std::function<R(Args...)>,
+ std::reference_wrapper<typename std::remove_reference<F>::type>
+ >
+{};
+
+struct hook{};
+
+}}}}
+
+namespace std{
+
+template<>
+struct is_void< ::boost::poly_collection::detail::is_invocable_fallback::hook>:
+ std::false_type
+{
+ template<typename F,typename... Args>
+ static constexpr bool is_invocable_f()
+ {
+ using namespace ::boost::poly_collection::detail::is_invocable_fallback;
+ return is_invocable<F,Args...>::value;
+ }
+
+ template<typename R,typename F,typename... Args>
+ static constexpr bool is_invocable_r_f()
+ {
+ using namespace ::boost::poly_collection::detail::is_invocable_fallback;
+ return is_invocable_r<R,F,Args...>::value;
+ }
+};
+
+} /* namespace std */
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+template<typename F,typename... Args>
+struct is_invocable:std::integral_constant<
+ bool,
+ std::is_void<is_invocable_fallback::hook>::template
+ is_invocable_f<F,Args...>()
+>{};
+
+template<typename R,typename F,typename... Args>
+struct is_invocable_r:std::integral_constant<
+ bool,
+ std::is_void<is_invocable_fallback::hook>::template
+ is_invocable_r_f<R,F,Args...>()
+>{};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/is_likely_stateless_lambda.hpp b/boost/poly_collection/detail/is_likely_stateless_lambda.hpp
new file mode 100644
index 0000000000..d8469c0dd3
--- /dev/null
+++ b/boost/poly_collection/detail/is_likely_stateless_lambda.hpp
@@ -0,0 +1,70 @@
+/* Copyright 2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_IS_LIKELY_STATELESS_LAMBDA_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_IS_LIKELY_STATELESS_LAMBDA_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <type_traits>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* Stateless lambda expressions have one (and only one) call operator and are
+ * convertible to a function pointer with the same signature. Non-lambda types
+ * could satisfy this too, hence the "likely" qualifier.
+ */
+
+template<typename T>
+struct has_one_operator_call_helper
+{
+ template<typename Q> static std::true_type test(decltype(&Q::operator())*);
+ template<typename> static std::false_type test(...);
+
+ using type=decltype(test<T>(nullptr));
+};
+
+template<typename T>
+using has_one_operator_call=typename has_one_operator_call_helper<T>::type;
+
+template<typename T>
+struct equivalent_function_pointer
+{
+ template<typename Q,typename R,typename... Args>
+ static auto helper(R (Q::*)(Args...)const)->R(*)(Args...);
+ template<typename Q,typename R,typename... Args>
+ static auto helper(R (Q::*)(Args...))->R(*)(Args...);
+
+ using type=decltype(helper(&T::operator()));
+};
+
+template<typename T,typename=void>
+struct is_likely_stateless_lambda:std::false_type{};
+
+template<typename T>
+struct is_likely_stateless_lambda<
+ T,
+ typename std::enable_if<has_one_operator_call<T>::value>::type
+>:std::is_convertible<
+ T,
+ typename equivalent_function_pointer<T>::type
+>{};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/is_nothrow_eq_comparable.hpp b/boost/poly_collection/detail/is_nothrow_eq_comparable.hpp
new file mode 100644
index 0000000000..7448b65e54
--- /dev/null
+++ b/boost/poly_collection/detail/is_nothrow_eq_comparable.hpp
@@ -0,0 +1,46 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_IS_NOTHROW_EQ_COMPARABLE_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_IS_NOTHROW_EQ_COMPARABLE_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/poly_collection/detail/is_equality_comparable.hpp>
+#include <type_traits>
+#include <utility>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+template<typename T,typename=void>
+struct is_nothrow_equality_comparable:std::false_type{};
+
+template<typename T>
+struct is_nothrow_equality_comparable<
+ T,
+ typename std::enable_if<
+ is_equality_comparable<T>::value
+ >::type
+>:std::integral_constant<
+ bool,
+ noexcept(std::declval<T>()==std::declval<T>())
+>{};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/iterator_impl.hpp b/boost/poly_collection/detail/iterator_impl.hpp
new file mode 100644
index 0000000000..e1893527d1
--- /dev/null
+++ b/boost/poly_collection/detail/iterator_impl.hpp
@@ -0,0 +1,242 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_ITERATOR_IMPL_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_ITERATOR_IMPL_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/poly_collection/detail/is_constructible.hpp>
+#include <boost/poly_collection/detail/iterator_traits.hpp>
+#include <type_traits>
+#include <typeinfo>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* Implementations of poly_collection::[const_][local_[base_]]iterator moved
+ * out of class to allow for use in deduced contexts.
+ */
+
+template<typename PolyCollection,bool Const>
+using iterator_impl_value_type=typename std::conditional<
+ Const,
+ const typename PolyCollection::value_type,
+ typename PolyCollection::value_type
+>::type;
+
+template<typename PolyCollection,bool Const>
+class iterator_impl:
+ public boost::iterator_facade<
+ iterator_impl<PolyCollection,Const>,
+ iterator_impl_value_type<PolyCollection,Const>,
+ boost::forward_traversal_tag
+ >
+{
+ using segment_type=typename PolyCollection::segment_type;
+ using const_segment_base_iterator=
+ typename PolyCollection::const_segment_base_iterator;
+ using const_segment_base_sentinel=
+ typename PolyCollection::const_segment_base_sentinel;
+ using const_segment_map_iterator=
+ typename PolyCollection::const_segment_map_iterator;
+
+public:
+ using value_type=iterator_impl_value_type<PolyCollection,Const>;
+
+private:
+ iterator_impl(
+ const_segment_map_iterator mapit,
+ const_segment_map_iterator mapend)noexcept:
+ mapit{mapit},mapend{mapend}
+ {
+ next_segment_position();
+ }
+
+ iterator_impl(
+ const_segment_map_iterator mapit_,const_segment_map_iterator mapend_,
+ const_segment_base_iterator segpos_)noexcept:
+ mapit{mapit_},mapend{mapend_},segpos{segpos_}
+ {
+ if(mapit!=mapend&&segpos==sentinel()){
+ ++mapit;
+ next_segment_position();
+ }
+ }
+
+public:
+ iterator_impl()=default;
+ iterator_impl(const iterator_impl&)=default;
+ iterator_impl& operator=(const iterator_impl&)=default;
+
+ template<bool Const2,typename std::enable_if<!Const2>::type* =nullptr>
+ iterator_impl(const iterator_impl<PolyCollection,Const2>& x):
+ mapit{x.mapit},mapend{x.mapend},segpos{x.segpos}{}
+
+private:
+ template<typename,bool>
+ friend class iterator_impl;
+ friend PolyCollection;
+ friend class boost::iterator_core_access;
+ template<typename>
+ friend struct iterator_traits;
+
+ value_type& dereference()const noexcept
+ {return const_cast<value_type&>(*segpos);}
+ bool equal(const iterator_impl& x)const noexcept{return segpos==x.segpos;}
+
+ void increment()noexcept
+ {
+ if(++segpos==sentinel()){
+ ++mapit;
+ next_segment_position();
+ }
+ }
+
+ void next_segment_position()noexcept
+ {
+ for(;mapit!=mapend;++mapit){
+ segpos=segment().begin();
+ if(segpos!=sentinel())return;
+ }
+ segpos=nullptr;
+ }
+
+ segment_type& segment()noexcept
+ {return const_cast<segment_type&>(mapit->second);}
+ const segment_type& segment()const noexcept{return mapit->second;}
+
+ const_segment_base_sentinel sentinel()const noexcept
+ {return segment().sentinel();}
+
+ const_segment_map_iterator mapit,mapend;
+ const_segment_base_iterator segpos;
+};
+
+template<typename PolyCollection,bool Const>
+struct poly_collection_of<iterator_impl<PolyCollection,Const>>
+{
+ using type=PolyCollection;
+};
+
+template<typename PolyCollection,typename BaseIterator>
+class local_iterator_impl:
+ public boost::iterator_adaptor<
+ local_iterator_impl<PolyCollection,BaseIterator>,
+ BaseIterator
+ >
+{
+ using segment_type=typename PolyCollection::segment_type;
+ using segment_base_iterator=typename PolyCollection::segment_base_iterator;
+ using const_segment_map_iterator=
+ typename PolyCollection::const_segment_map_iterator;
+
+ template<typename Iterator>
+ local_iterator_impl(
+ const_segment_map_iterator mapit,
+ Iterator it):
+ local_iterator_impl::iterator_adaptor_{BaseIterator(it)},
+ mapit{mapit}
+ {}
+
+public:
+ using base_iterator=BaseIterator;
+
+ local_iterator_impl()=default;
+ local_iterator_impl(const local_iterator_impl&)=default;
+ local_iterator_impl& operator=(const local_iterator_impl&)=default;
+
+ template<
+ typename BaseIterator2,
+ typename std::enable_if<
+ std::is_convertible<BaseIterator2,BaseIterator>::value
+ >::type* =nullptr
+ >
+ local_iterator_impl(
+ const local_iterator_impl<PolyCollection,BaseIterator2>& x):
+ local_iterator_impl::iterator_adaptor_{x.base()},
+ mapit{x.mapit}{}
+
+ template<
+ typename BaseIterator2,
+ typename std::enable_if<
+ !std::is_convertible<BaseIterator2,BaseIterator>::value&&
+ is_constructible<BaseIterator,BaseIterator2>::value
+ >::type* =nullptr
+ >
+ explicit local_iterator_impl(
+ const local_iterator_impl<PolyCollection,BaseIterator2>& x):
+ local_iterator_impl::iterator_adaptor_{BaseIterator(x.base())},
+ mapit{x.mapit}{}
+
+ template<
+ typename BaseIterator2,
+ typename std::enable_if<
+ !is_constructible<BaseIterator,BaseIterator2>::value&&
+ is_constructible<BaseIterator,segment_base_iterator>::value&&
+ is_constructible<BaseIterator2,segment_base_iterator>::value
+ >::type* =nullptr
+ >
+ explicit local_iterator_impl(
+ const local_iterator_impl<PolyCollection,BaseIterator2>& x):
+ local_iterator_impl::iterator_adaptor_{
+ base_iterator_from(x.segment(),x.base())},
+ mapit{x.mapit}{}
+
+ /* define [] to avoid Boost.Iterator operator_brackets_proxy mess */
+
+ template<typename DifferenceType>
+ typename std::iterator_traits<BaseIterator>::reference
+ operator[](DifferenceType n)const{return *(*this+n);}
+
+private:
+ template<typename,typename>
+ friend class local_iterator_impl;
+ friend PolyCollection;
+ template<typename>
+ friend struct iterator_traits;
+
+ template<typename BaseIterator2>
+ static BaseIterator base_iterator_from(
+ const segment_type& s,BaseIterator2 it)
+ {
+ segment_base_iterator bit=s.begin();
+ return BaseIterator{bit+(it-static_cast<BaseIterator2>(bit))};
+ }
+
+ base_iterator base()const noexcept
+ {return local_iterator_impl::iterator_adaptor_::base();}
+ const std::type_info& type_info()const{return *mapit->first;}
+ segment_type& segment()noexcept
+ {return const_cast<segment_type&>(mapit->second);}
+ const segment_type& segment()const noexcept{return mapit->second;}
+
+ const_segment_map_iterator mapit;
+};
+
+template<typename PolyCollection,typename BaseIterator>
+struct poly_collection_of<local_iterator_impl<PolyCollection,BaseIterator>>
+{
+ using type=PolyCollection;
+};
+
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/iterator_traits.hpp b/boost/poly_collection/detail/iterator_traits.hpp
new file mode 100644
index 0000000000..732535a8b4
--- /dev/null
+++ b/boost/poly_collection/detail/iterator_traits.hpp
@@ -0,0 +1,116 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_ITERATOR_TRAITS_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_ITERATOR_TRAITS_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <iterator>
+#include <type_traits>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* (Internal) bunch of traits-grouped functions for const-preserving
+ * interoperatibility between iterators and local iterators of a
+ * poly_collection.
+ */
+
+template<typename Iterator>
+struct poly_collection_of /* to be specialized for iterator impls */
+{
+ using type=void;
+};
+
+namespace poly_collection_impl{
+
+template<typename Model,typename Allocator>
+class poly_collection;
+
+}
+
+template<typename PolyCollection>
+struct model_of;
+
+template<typename Model,typename Allocator>
+struct model_of<poly_collection_impl::poly_collection<Model,Allocator>>
+{
+ using type=Model;
+};
+
+template<typename Iterator>
+struct iterator_traits
+{
+ using container_type=typename poly_collection_of<Iterator>::type;
+ using is_const_iterator=typename std::is_const<
+ typename std::remove_reference<
+ typename std::iterator_traits<Iterator>::reference
+ >::type
+ >::type;
+ using iterator=typename std::conditional<
+ is_const_iterator::value,
+ typename container_type::const_iterator,
+ typename container_type::iterator
+ >::type;
+ using base_segment_info_iterator=typename std::conditional<
+ is_const_iterator::value,
+ typename container_type::const_base_segment_info_iterator,
+ typename container_type::base_segment_info_iterator
+ >::type;
+ using local_base_iterator=typename std::conditional<
+ is_const_iterator::value,
+ typename container_type::const_local_base_iterator,
+ typename container_type::local_base_iterator
+ >::type;
+ template<typename T>
+ using local_iterator=typename std::conditional<
+ is_const_iterator::value,
+ typename container_type::template const_local_iterator<T>,
+ typename container_type::template local_iterator<T>
+ >::type;
+
+ static base_segment_info_iterator
+ base_segment_info_iterator_from(iterator it)noexcept{return it.mapit;}
+
+ static base_segment_info_iterator
+ base_segment_info_iterator_from(local_base_iterator it)noexcept
+ {return it.mapit;}
+
+ static base_segment_info_iterator
+ end_base_segment_info_iterator_from(iterator it)noexcept{return it.mapend;}
+
+ static local_base_iterator
+ local_base_iterator_from(iterator it)noexcept
+ {
+ return {
+ it.mapit,
+ model_of<container_type>::type::nonconst_iterator(it.segpos)
+ };
+ }
+
+ static iterator
+ iterator_from(
+ local_base_iterator lbit,base_segment_info_iterator mapend)noexcept
+ {
+ return {lbit.mapit,mapend.base(),lbit.base()};
+ }
+};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/newdelete_allocator.hpp b/boost/poly_collection/detail/newdelete_allocator.hpp
new file mode 100644
index 0000000000..1c66db3b7a
--- /dev/null
+++ b/boost/poly_collection/detail/newdelete_allocator.hpp
@@ -0,0 +1,102 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_NEWDELETE_ALLOCATOR_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_NEWDELETE_ALLOCATOR_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/poly_collection/detail/is_constructible.hpp>
+#include <memory>
+#include <new>
+#include <utility>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* In order to comply with [container.requirements.general]/3,
+ * newdelete_allocator_adaptor<Allocator> overrides
+ * Allocator::construct/destroy with vanilla new/delete implementations.
+ * Used therefore in all auxiliary internal structures.
+ */
+
+template<typename Allocator>
+struct newdelete_allocator_adaptor:Allocator
+{
+ using traits=std::allocator_traits<Allocator>;
+
+ using value_type=typename traits::value_type;
+ using size_type=typename traits::size_type;
+ using difference_type=typename traits::difference_type;
+ using pointer=typename traits::pointer;
+ using const_pointer=typename traits::const_pointer;
+ using void_pointer=typename traits::void_pointer;
+ using const_void_pointer=typename traits::const_void_pointer;
+ using propagate_on_container_copy_assignment=
+ typename traits::propagate_on_container_copy_assignment;
+ using propagate_on_container_move_assignment=
+ typename traits::propagate_on_container_move_assignment;
+ using propagate_on_container_swap=
+ typename traits::propagate_on_container_swap;
+
+ template<typename U>
+ struct rebind
+ {
+ using other=newdelete_allocator_adaptor<
+ typename traits::template rebind_alloc<U>>;
+ };
+
+ newdelete_allocator_adaptor()=default;
+ newdelete_allocator_adaptor(const newdelete_allocator_adaptor&)=default;
+
+ template<
+ typename Allocator2,
+ typename std::enable_if<
+ is_constructible<Allocator,Allocator2>::value
+ >::type* =nullptr
+ >
+ newdelete_allocator_adaptor(const Allocator2& x)noexcept:Allocator{x}{}
+
+ template<
+ typename Allocator2,
+ typename std::enable_if<
+ is_constructible<Allocator,Allocator2>::value
+ >::type* =nullptr
+ >
+ newdelete_allocator_adaptor(
+ const newdelete_allocator_adaptor<Allocator2>& x)noexcept:
+ Allocator{static_cast<const Allocator2&>(x)}{}
+
+ newdelete_allocator_adaptor& operator=(
+ const newdelete_allocator_adaptor&)=default;
+
+ template<typename T,typename... Args>
+ void construct(T* p,Args&&... args)
+ {
+ ::new ((void*)p) T(std::forward<Args>(args)...);
+ }
+
+ template<typename T>
+ void destroy(T* p)
+ {
+ p->~T();
+ }
+};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/packed_segment.hpp b/boost/poly_collection/detail/packed_segment.hpp
new file mode 100644
index 0000000000..5500a2d5fc
--- /dev/null
+++ b/boost/poly_collection/detail/packed_segment.hpp
@@ -0,0 +1,318 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_PACKED_SEGMENT_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_PACKED_SEGMENT_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/poly_collection/detail/newdelete_allocator.hpp>
+#include <boost/poly_collection/detail/segment_backend.hpp>
+#include <boost/poly_collection/detail/value_holder.hpp>
+#include <memory>
+#include <new>
+#include <vector>
+#include <utility>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* segment_backend implementation where value_type& and Concrete& actually refer
+ * to the same stored entity.
+ *
+ * Requires:
+ * - [const_]base_iterator is a stride iterator constructible from
+ * {value_type*,sizeof(store_value_type)}.
+ * - Model provides a function value_ptr for
+ * const Concrete* -> const value_type* conversion.
+ */
+
+template<typename Model,typename Concrete,typename Allocator>
+class packed_segment:public segment_backend<Model>
+{
+ using value_type=typename Model::value_type;
+ using store_value_type=value_holder<Concrete>;
+ using store=std::vector<
+ store_value_type,
+ value_holder_allocator_adaptor<
+ typename std::allocator_traits<Allocator>::
+ template rebind_alloc<store_value_type>
+ >
+ >;
+ using store_iterator=typename store::iterator;
+ using const_store_iterator=typename store::const_iterator;
+ using segment_backend=detail::segment_backend<Model>;
+ using typename segment_backend::segment_backend_unique_ptr;
+ using typename segment_backend::value_pointer;
+ using typename segment_backend::const_value_pointer;
+ using typename segment_backend::base_iterator;
+ using typename segment_backend::const_base_iterator;
+ using const_iterator=
+ typename segment_backend::template const_iterator<Concrete>;
+ using typename segment_backend::base_sentinel;
+ using typename segment_backend::range;
+ using segment_allocator_type=newdelete_allocator_adaptor<
+ typename std::allocator_traits<Allocator>::
+ template rebind_alloc<packed_segment>
+ >;
+public:
+ virtual ~packed_segment()=default;
+
+ virtual segment_backend_unique_ptr copy()const
+ {
+ return new_(s.get_allocator(),store{s});
+ }
+
+ virtual segment_backend_unique_ptr empty_copy()const
+ {
+ return new_(s.get_allocator(),s.get_allocator());
+ }
+
+ virtual bool equal(const segment_backend& x)const
+ {
+ return s==static_cast<const packed_segment&>(x).s;
+ }
+
+ virtual base_iterator begin()const noexcept{return nv_begin();}
+
+ base_iterator nv_begin()const noexcept
+ {
+ return {value_ptr(s.data()),sizeof(store_value_type)};
+ }
+
+ virtual base_iterator end()const noexcept{return nv_end();}
+
+ base_iterator nv_end()const noexcept
+ {
+ return {value_ptr(s.data()+s.size()),sizeof(store_value_type)};
+ }
+
+ virtual bool empty()const noexcept{return nv_empty();}
+ bool nv_empty()const noexcept{return s.empty();}
+ virtual std::size_t size()const noexcept{return nv_size();}
+ std::size_t nv_size()const noexcept{return s.size();}
+ virtual std::size_t max_size()const noexcept{return nv_max_size();}
+ std::size_t nv_max_size()const noexcept{return s.max_size();}
+ virtual std::size_t capacity()const noexcept{return nv_capacity();}
+ std::size_t nv_capacity()const noexcept{return s.capacity();}
+ virtual base_sentinel reserve(std::size_t n){return nv_reserve(n);}
+ base_sentinel nv_reserve(std::size_t n)
+ {s.reserve(n);return sentinel();}
+ virtual base_sentinel shrink_to_fit(){return nv_shrink_to_fit();}
+ base_sentinel nv_shrink_to_fit()
+ {s.shrink_to_fit();return sentinel();}
+
+ template<typename Iterator,typename... Args>
+ range nv_emplace(Iterator p,Args&&... args)
+ {
+ return range_from(
+ s.emplace(
+ iterator_from(p),
+ value_holder_emplacing_ctor,std::forward<Args>(args)...));
+ }
+
+ template<typename... Args>
+ range nv_emplace_back(Args&&... args)
+ {
+ s.emplace_back(value_holder_emplacing_ctor,std::forward<Args>(args)...);
+ return range_from(s.size()-1);
+ }
+
+ virtual range push_back(const_value_pointer x)
+ {return nv_push_back(const_concrete_ref(x));}
+
+ range nv_push_back(const Concrete& x)
+ {
+ s.emplace_back(x);
+ return range_from(s.size()-1);
+ }
+
+ virtual range push_back_move(value_pointer x)
+ {return nv_push_back(std::move(concrete_ref(x)));}
+
+ range nv_push_back(Concrete&& x)
+ {
+ s.emplace_back(std::move(x));
+ return range_from(s.size()-1);
+ }
+
+ virtual range insert(const_base_iterator p,const_value_pointer x)
+ {return nv_insert(const_iterator(p),const_concrete_ref(x));}
+
+ range nv_insert(const_iterator p,const Concrete& x)
+ {
+ return range_from(s.emplace(iterator_from(p),x));
+ }
+
+ virtual range insert_move(const_base_iterator p,value_pointer x)
+ {return nv_insert(const_iterator(p),std::move(concrete_ref(x)));}
+
+ range nv_insert(const_iterator p,Concrete&& x)
+ {
+ return range_from(s.emplace(iterator_from(p),std::move(x)));
+ }
+
+ template<typename InputIterator>
+ range nv_insert(InputIterator first,InputIterator last)
+ {
+ return nv_insert(
+ const_iterator(concrete_ptr(s.data()+s.size())),first,last);
+ }
+
+ template<typename InputIterator>
+ range nv_insert(const_iterator p,InputIterator first,InputIterator last)
+ {
+ return range_from(s.insert(iterator_from(p),first,last));
+ }
+
+ virtual range erase(const_base_iterator p)
+ {return nv_erase(const_iterator(p));}
+
+ range nv_erase(const_iterator p)
+ {
+ return range_from(s.erase(iterator_from(p)));
+ }
+
+ virtual range erase(const_base_iterator first,const_base_iterator last)
+ {return nv_erase(const_iterator(first),const_iterator(last));}
+
+ range nv_erase(const_iterator first,const_iterator last)
+ {
+ return range_from(s.erase(iterator_from(first),iterator_from(last)));
+ }
+
+ virtual range erase_till_end(const_base_iterator first)
+ {
+ return range_from(s.erase(iterator_from(first),s.end()));
+ }
+
+ virtual range erase_from_begin(const_base_iterator last)
+ {
+ return range_from(s.erase(s.begin(),iterator_from(last)));
+ }
+
+ virtual base_sentinel clear()noexcept{return nv_clear();}
+ base_sentinel nv_clear()noexcept{s.clear();return sentinel();}
+
+private:
+ friend Model;
+
+ template<typename... Args>
+ static segment_backend_unique_ptr new_(
+ segment_allocator_type al,Args&&... args)
+ {
+ auto p=std::allocator_traits<segment_allocator_type>::allocate(al,1);
+ try{
+ ::new ((void*)p) packed_segment{std::forward<Args>(args)...};
+ }
+ catch(...){
+ std::allocator_traits<segment_allocator_type>::deallocate(al,p,1);
+ throw;
+ }
+ return {p,&delete_};
+ }
+
+ static void delete_(segment_backend* p)
+ {
+ auto q=static_cast<packed_segment*>(p);
+ auto al=segment_allocator_type{q->s.get_allocator()};
+ q->~packed_segment();
+ std::allocator_traits<segment_allocator_type>::deallocate(al,q,1);
+ }
+
+ packed_segment(const Allocator& al):s{typename store::allocator_type{al}}{}
+ packed_segment(store&& s):s{std::move(s)}{}
+
+ static Concrete& concrete_ref(value_pointer p)noexcept
+ {
+ return *static_cast<Concrete*>(p);
+ }
+
+ static const Concrete& const_concrete_ref(const_value_pointer p)noexcept
+ {
+ return *static_cast<const Concrete*>(p);
+ }
+
+ static Concrete* concrete_ptr(store_value_type* p)noexcept
+ {
+ return reinterpret_cast<Concrete*>(
+ static_cast<value_holder_base<Concrete>*>(p));
+ }
+
+ static const Concrete* const_concrete_ptr(const store_value_type* p)noexcept
+ {
+ return concrete_ptr(const_cast<store_value_type*>(p));
+ }
+
+ static value_type* value_ptr(const store_value_type* p)noexcept
+ {
+ return const_cast<value_type*>(Model::value_ptr(const_concrete_ptr(p)));
+ }
+
+ static const store_value_type* const_store_value_type_ptr(
+ const Concrete* p)noexcept
+ {
+ return static_cast<const value_holder<Concrete>*>(
+ reinterpret_cast<const value_holder_base<Concrete>*>(p));
+ }
+
+ /* It would have sufficed if iterator_from returned const_store_iterator
+ * except for the fact that some old versions of libstdc++ claiming to be
+ * C++11 compliant do not however provide std::vector modifier ops taking
+ * const_iterator's.
+ */
+
+ store_iterator iterator_from(const_base_iterator p)
+ {
+ return iterator_from(static_cast<const_iterator>(p));
+ }
+
+ store_iterator iterator_from(const_iterator p)
+ {
+ return s.begin()+(const_store_value_type_ptr(p)-s.data());
+ }
+
+ base_sentinel sentinel()const noexcept
+ {
+ return base_iterator{
+ value_ptr(s.data()+s.size()),
+ sizeof(store_value_type)
+ };
+ }
+
+ range range_from(const_store_iterator it)const
+ {
+ return {
+ {value_ptr(s.data()+(it-s.begin())),sizeof(store_value_type)},
+ sentinel()
+ };
+ }
+
+ range range_from(std::size_t n)const
+ {
+ return {
+ {value_ptr(s.data()+n),sizeof(store_value_type)},
+ sentinel()
+ };
+ }
+
+ store s;
+};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/poly_collection.hpp b/boost/poly_collection/detail/poly_collection.hpp
new file mode 100644
index 0000000000..eebd75ca89
--- /dev/null
+++ b/boost/poly_collection/detail/poly_collection.hpp
@@ -0,0 +1,1176 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_POLY_COLLECTION_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_POLY_COLLECTION_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <algorithm>
+#include <boost/assert.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/poly_collection/detail/iterator_impl.hpp>
+#include <boost/poly_collection/detail/is_acceptable.hpp>
+#include <boost/poly_collection/detail/is_constructible.hpp>
+#include <boost/poly_collection/detail/is_final.hpp>
+#include <boost/poly_collection/detail/newdelete_allocator.hpp>
+#include <boost/poly_collection/detail/segment.hpp>
+#include <boost/poly_collection/detail/type_info_map.hpp>
+#include <boost/poly_collection/exception.hpp>
+#include <iterator>
+#include <type_traits>
+#include <typeinfo>
+#include <utility>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+namespace poly_collection_impl{
+
+/* common implementation for all polymorphic collections */
+
+template<typename Model,typename Allocator>
+class poly_collection
+{
+ template<typename T>
+ static const std::type_info& subtypeid(const T& x)
+ {return Model::subtypeid(x);}
+ template<typename...>
+ struct for_all_types{using type=void*;};
+ template<typename... T>
+ using for_all=typename for_all_types<T...>::type;
+ template<typename T>
+ struct is_subtype: /* using makes VS2015 choke, hence we derive */
+ Model::template is_subtype<typename std::decay<T>::type>{};
+ template<typename T>
+ using enable_if_subtype=
+ typename std::enable_if<is_subtype<T>::value>::type*;
+ template<typename T>
+ using enable_if_not_subtype=
+ typename std::enable_if<!is_subtype<T>::value>::type*;
+ template<typename T>
+ using is_acceptable=
+ detail::is_acceptable<typename std::decay<T>::type,Model>;
+ template<typename T>
+ using enable_if_acceptable=
+ typename std::enable_if<is_acceptable<T>::value>::type*;
+ template<typename T>
+ using enable_if_not_acceptable=
+ typename std::enable_if<!is_acceptable<T>::value>::type*;
+ template<typename InputIterator>
+ using enable_if_derefs_to_subtype=enable_if_subtype<
+ typename std::iterator_traits<InputIterator>::value_type
+ >;
+ template<typename T>
+ using is_terminal=
+ typename Model::template is_terminal<typename std::decay<T>::type>;
+ template<typename T>
+ using enable_if_terminal=
+ typename std::enable_if<is_terminal<T>::value>::type*;
+ template<typename T>
+ using enable_if_not_terminal=
+ typename std::enable_if<!is_terminal<T>::value>::type*;
+ template<typename InputIterator>
+ using derefs_to_terminal=is_terminal<
+ typename std::iterator_traits<InputIterator>::value_type
+ >;
+ template<typename InputIterator>
+ using enable_if_derefs_to_terminal=
+ typename std::enable_if<derefs_to_terminal<InputIterator>::value>::type*;
+ template<typename InputIterator>
+ using enable_if_derefs_to_not_terminal=
+ typename std::enable_if<!derefs_to_terminal<InputIterator>::value>::type*;
+ template<typename T,typename U>
+ using enable_if_not_same=typename std::enable_if<
+ !std::is_same<
+ typename std::decay<T>::type,typename std::decay<U>::type
+ >::value
+ >::type*;
+ template<typename T,typename U>
+ using enable_if_constructible=
+ typename std::enable_if<is_constructible<T,U>::value>::type*;
+ template<typename T,typename U>
+ using enable_if_not_constructible=
+ typename std::enable_if<!is_constructible<T,U>::value>::type*;
+
+ using segment_type=detail::segment<Model,Allocator>;
+ using segment_base_iterator=typename segment_type::base_iterator;
+ using const_segment_base_iterator=
+ typename segment_type::const_base_iterator;
+ using segment_base_sentinel=typename segment_type::base_sentinel;
+ using const_segment_base_sentinel=
+ typename segment_type::const_base_sentinel;
+ template<typename T>
+ using segment_iterator=typename segment_type::template iterator<T>;
+ template<typename T>
+ using const_segment_iterator=
+ typename segment_type::template const_iterator<T>;
+ using segment_map=type_info_map<
+ segment_type,
+ newdelete_allocator_adaptor<
+ typename std::allocator_traits<Allocator>::template
+ rebind_alloc<segment_type>
+ >
+ >;
+ using segment_map_allocator_type=typename segment_map::allocator_type;
+ using segment_map_iterator=typename segment_map::iterator;
+ using const_segment_map_iterator=typename segment_map::const_iterator;
+
+public:
+ /* types */
+
+ using value_type=typename segment_type::value_type;
+ using allocator_type=Allocator;
+ using size_type=std::size_t;
+ using difference_type=std::ptrdiff_t;
+ using reference=value_type&;
+ using const_reference=const value_type&;
+ using pointer=typename std::allocator_traits<Allocator>::pointer;
+ using const_pointer=typename std::allocator_traits<Allocator>::const_pointer;
+
+private:
+ template<typename,bool>
+ friend class detail::iterator_impl;
+ template<typename,typename>
+ friend class detail::local_iterator_impl;
+ template<bool Const>
+ using iterator_impl=detail::iterator_impl<poly_collection,Const>;
+ template<typename BaseIterator>
+ using local_iterator_impl=
+ detail::local_iterator_impl<poly_collection,BaseIterator>;
+
+public:
+ using iterator=iterator_impl<false>;
+ using const_iterator=iterator_impl<true>;
+ using local_base_iterator=local_iterator_impl<segment_base_iterator>;
+ using const_local_base_iterator=
+ local_iterator_impl<const_segment_base_iterator>;
+ template<typename T>
+ using local_iterator=local_iterator_impl<segment_iterator<T>>;
+ template<typename T>
+ using const_local_iterator=local_iterator_impl<const_segment_iterator<T>>;
+
+ class const_base_segment_info
+ {
+ public:
+ const_base_segment_info(const const_base_segment_info&)=default;
+ const_base_segment_info& operator=(const const_base_segment_info&)=default;
+
+ const_local_base_iterator begin()const noexcept
+ {return {it,it->second.begin()};}
+ const_local_base_iterator end()const noexcept
+ {return {it,it->second.end()};}
+ const_local_base_iterator cbegin()const noexcept{return begin();}
+ const_local_base_iterator cend()const noexcept{return end();}
+
+ template<typename T>
+ const_local_iterator<T> begin()const noexcept
+ {return const_local_iterator<T>{begin()};}
+ template<typename T>
+ const_local_iterator<T> end()const noexcept
+ {return const_local_iterator<T>{end()};}
+ template<typename T>
+ const_local_iterator<T> cbegin()const noexcept{return begin<T>();}
+ template<typename T>
+ const_local_iterator<T> cend()const noexcept{return end<T>();}
+
+ const std::type_info& type_info()const{return *it->first;}
+
+ protected:
+ friend class poly_collection;
+
+ const_base_segment_info(const_segment_map_iterator it)noexcept:it{it}{}
+
+ const_segment_map_iterator it;
+ };
+
+ class base_segment_info:public const_base_segment_info
+ {
+ public:
+ base_segment_info(const base_segment_info&)=default;
+ base_segment_info& operator=(const base_segment_info&)=default;
+
+ using const_base_segment_info::begin;
+ using const_base_segment_info::end;
+
+ local_base_iterator begin()noexcept
+ {return {this->it,this->it->second.begin()};}
+ local_base_iterator end()noexcept
+ {return {this->it,this->it->second.end()};}
+
+ template<typename T>
+ local_iterator<T> begin()noexcept{return local_iterator<T>{begin()};}
+ template<typename T>
+ local_iterator<T> end()noexcept{return local_iterator<T>{end()};}
+
+ private:
+ friend class poly_collection;
+
+ using const_base_segment_info::const_base_segment_info;
+ };
+
+ template<typename T>
+ class const_segment_info
+ {
+ public:
+ const_segment_info(const const_segment_info&)=default;
+ const_segment_info& operator=(const const_segment_info&)=default;
+
+ const_local_iterator<T> begin()const noexcept
+ {return {it,it->second.begin()};}
+ const_local_iterator<T> end()const noexcept
+ {return {it,it->second.end()};}
+ const_local_iterator<T> cbegin()const noexcept{return begin();}
+ const_local_iterator<T> cend()const noexcept{return end();}
+
+ protected:
+ friend class poly_collection;
+
+ const_segment_info(const_segment_map_iterator it)noexcept:it{it}{}
+
+ const_segment_map_iterator it;
+ };
+
+ template<typename T>
+ class segment_info:public const_segment_info<T>
+ {
+ public:
+ segment_info(const segment_info&)=default;
+ segment_info& operator=(const segment_info&)=default;
+
+ using const_segment_info<T>::begin;
+ using const_segment_info<T>::end;
+
+ local_iterator<T> begin()noexcept
+ {return {this->it,this->it->second.begin()};}
+ local_iterator<T> end()noexcept
+ {return {this->it,this->it->second.end()};}
+
+ private:
+ friend class poly_collection;
+
+ using const_segment_info<T>::const_segment_info;
+ };
+
+private:
+ template<typename SegmentInfo>
+ class segment_info_iterator_impl:
+ public boost::iterator_adaptor<
+ segment_info_iterator_impl<SegmentInfo>,
+ const_segment_map_iterator,
+ SegmentInfo,
+ std::input_iterator_tag,
+ SegmentInfo
+ >
+ {
+ segment_info_iterator_impl(const_segment_map_iterator it):
+ segment_info_iterator_impl::iterator_adaptor_{it}{}
+
+ public:
+ segment_info_iterator_impl()=default;
+ segment_info_iterator_impl(const segment_info_iterator_impl&)=default;
+ segment_info_iterator_impl& operator=(
+ const segment_info_iterator_impl&)=default;
+
+ template<
+ typename SegmentInfo2,
+ typename std::enable_if<
+ std::is_base_of<SegmentInfo,SegmentInfo2>::value
+ >::type* =nullptr
+ >
+ segment_info_iterator_impl(
+ const segment_info_iterator_impl<SegmentInfo2>& x):
+ segment_info_iterator_impl::iterator_adaptor_{x.base()}{}
+
+ template<
+ typename SegmentInfo2,
+ typename std::enable_if<
+ std::is_base_of<SegmentInfo,SegmentInfo2>::value
+ >::type* =nullptr
+ >
+ segment_info_iterator_impl& operator=(
+ const segment_info_iterator_impl<SegmentInfo2>& x)
+ {
+ this->base_reference()=x.base();
+ return *this;
+ }
+
+ private:
+ template<typename>
+ friend class segment_info_iterator_impl;
+ friend class poly_collection;
+ friend class boost::iterator_core_access;
+ template<typename>
+ friend struct detail::iterator_traits;
+
+ SegmentInfo dereference()const noexcept{return this->base();}
+ };
+
+public:
+ using base_segment_info_iterator=
+ segment_info_iterator_impl<base_segment_info>;
+ using const_base_segment_info_iterator=
+ segment_info_iterator_impl<const_base_segment_info>;
+
+private:
+ template<typename Iterator>
+ static Iterator nonconst_hlp(Iterator);
+ static iterator nonconst_hlp(const_iterator);
+ static local_base_iterator nonconst_hlp(const_local_base_iterator);
+ template<typename T>
+ static local_iterator<T> nonconst_hlp(const_local_iterator<T>);
+ static base_segment_info_iterator nonconst_hlp(
+ const_base_segment_info_iterator);
+
+ template<typename Iterator>
+ using nonconst_version=decltype(nonconst_hlp(std::declval<Iterator>()));
+
+public:
+ class const_segment_traversal_info
+ {
+ public:
+ const_segment_traversal_info(const const_segment_traversal_info&)=default;
+ const_segment_traversal_info& operator=(
+ const const_segment_traversal_info&)=default;
+
+ const_base_segment_info_iterator begin()const noexcept
+ {return pmap->cbegin();}
+ const_base_segment_info_iterator end()const noexcept{return pmap->cend();}
+ const_base_segment_info_iterator cbegin()const noexcept{return begin();}
+ const_base_segment_info_iterator cend()const noexcept{return end();}
+
+ protected:
+ friend class poly_collection;
+
+ const_segment_traversal_info(const segment_map& map)noexcept:
+ pmap{const_cast<segment_map*>(&map)}{}
+
+ segment_map* pmap;
+ };
+
+ class segment_traversal_info:public const_segment_traversal_info
+ {
+ public:
+ segment_traversal_info(const segment_traversal_info&)=default;
+ segment_traversal_info& operator=(const segment_traversal_info&)=default;
+
+ using const_segment_traversal_info::begin;
+ using const_segment_traversal_info::end;
+
+ base_segment_info_iterator begin()noexcept{return this->pmap->cbegin();}
+ base_segment_info_iterator end()noexcept{return this->pmap->cend();}
+
+ private:
+ friend class poly_collection;
+
+ using const_segment_traversal_info::const_segment_traversal_info;
+ };
+
+ /* construct/destroy/copy */
+
+ poly_collection()=default;
+ poly_collection(const poly_collection&)=default;
+ poly_collection(poly_collection&&)=default;
+ explicit poly_collection(const allocator_type& al):
+ map{segment_map_allocator_type{al}}{}
+ poly_collection(const poly_collection& x,const allocator_type& al):
+ map{x.map,segment_map_allocator_type{al}}{}
+ poly_collection(poly_collection&& x,const allocator_type& al):
+ map{std::move(x.map),segment_map_allocator_type{al}}{}
+
+ template<typename InputIterator>
+ poly_collection(
+ InputIterator first,InputIterator last,
+ const allocator_type& al=allocator_type{}):
+ map{segment_map_allocator_type{al}}
+ {
+ this->insert(first,last);
+ }
+
+ // TODO: what to do with initializer_list?
+
+ poly_collection& operator=(const poly_collection&)=default;
+ poly_collection& operator=(poly_collection&&)=default;
+
+ allocator_type get_allocator()const noexcept{return map.get_allocator();}
+
+ /* type registration */
+
+ template<
+ typename... T,
+ for_all<enable_if_acceptable<T>...> =nullptr
+ >
+ void register_types()
+ {
+ /* http://twitter.com/SeanParent/status/558765089294020609 */
+
+ using seq=int[1+sizeof...(T)];
+ (void)seq{
+ 0,
+ (map.insert(
+ typeid(T),segment_type::template make<T>(get_allocator())),0)...
+ };
+ }
+
+ bool is_registered(const std::type_info& info)const
+ {
+ return map.find(info)!=map.end();
+ }
+
+ template<typename T,enable_if_acceptable<T> =nullptr>
+ bool is_registered()const
+ {
+ return is_registered(typeid(T));
+ }
+
+ /* iterators */
+
+ iterator begin()noexcept{return {map.begin(),map.end()};}
+ iterator end()noexcept{return {map.end(),map.end()};}
+ const_iterator begin()const noexcept{return {map.begin(),map.end()};}
+ const_iterator end()const noexcept{return {map.end(),map.end()};}
+ const_iterator cbegin()const noexcept{return begin();}
+ const_iterator cend()const noexcept{return end();}
+
+ local_base_iterator begin(const std::type_info& info)
+ {
+ auto it=get_map_iterator_for(info);
+ return {it,segment(it).begin()};
+ }
+
+ local_base_iterator end(const std::type_info& info)
+ {
+ auto it=get_map_iterator_for(info);
+ return {it,segment(it).end()};
+ }
+
+ const_local_base_iterator begin(const std::type_info& info)const
+ {
+ auto it=get_map_iterator_for(info);
+ return {it,segment(it).begin()};
+ }
+
+ const_local_base_iterator end(const std::type_info& info)const
+ {
+ auto it=get_map_iterator_for(info);
+ return {it,segment(it).end()};
+ }
+
+ const_local_base_iterator cbegin(const std::type_info& info)const
+ {return begin(info);}
+ const_local_base_iterator cend(const std::type_info& info)const
+ {return end(info);}
+
+ template<typename T,enable_if_acceptable<T> =nullptr>
+ local_iterator<T> begin()
+ {
+ auto it=get_map_iterator_for(typeid(T));
+ return {it,segment(it).template begin<T>()};
+ }
+
+ template<typename T,enable_if_acceptable<T> =nullptr>
+ local_iterator<T> end()
+ {
+ auto it=get_map_iterator_for(typeid(T));
+ return {it,segment(it).template end<T>()};
+ }
+
+ template<typename T,enable_if_acceptable<T> =nullptr>
+ const_local_iterator<T> begin()const
+ {
+ auto it=get_map_iterator_for(typeid(T));
+ return {it,segment(it).template begin<T>()};
+ }
+
+ template<typename T,enable_if_acceptable<T> =nullptr>
+ const_local_iterator<T> end()const
+ {
+ auto it=get_map_iterator_for(typeid(T));
+ return {it,segment(it).template end<T>()};
+ }
+
+ template<typename T,enable_if_acceptable<T> =nullptr>
+ const_local_iterator<T> cbegin()const{return begin<T>();}
+
+ template<typename T,enable_if_acceptable<T> =nullptr>
+ const_local_iterator<T> cend()const{return end<T>();}
+
+ base_segment_info segment(const std::type_info& info)
+ {
+ return get_map_iterator_for(info);
+ }
+
+ const_base_segment_info segment(const std::type_info& info)const
+ {
+ return get_map_iterator_for(info);
+ }
+
+ template<typename T,enable_if_acceptable<T> =nullptr>
+ segment_info<T> segment(){return get_map_iterator_for(typeid(T));}
+
+ template<typename T,enable_if_acceptable<T> =nullptr>
+ const_segment_info<T> segment()const{return get_map_iterator_for(typeid(T));}
+
+ segment_traversal_info segment_traversal()noexcept{return map;}
+ const_segment_traversal_info segment_traversal()const noexcept{return map;}
+
+ /* capacity */
+
+ bool empty()const noexcept
+ {
+ for(const auto& x:map)if(!x.second.empty())return false;
+ return true;
+ }
+
+ bool empty(const std::type_info& info)const
+ {
+ return segment(get_map_iterator_for(info)).empty();
+ }
+
+ template<typename T,enable_if_acceptable<T> =nullptr>
+ bool empty()const
+ {
+ return segment(get_map_iterator_for(typeid(T))).template empty<T>();
+ }
+
+ size_type size()const noexcept
+ {
+ size_type res=0;
+ for(const auto& x:map)res+=x.second.size();
+ return res;
+ }
+
+ size_type size(const std::type_info& info)const
+ {
+ return segment(get_map_iterator_for(info)).size();
+ }
+
+ template<typename T,enable_if_acceptable<T> =nullptr>
+ size_type size()const
+ {
+ return segment(get_map_iterator_for(typeid(T))).template size<T>();
+ }
+
+ size_type max_size(const std::type_info& info)const
+ {
+ return segment(get_map_iterator_for(info)).max_size();
+ }
+
+ template<typename T,enable_if_acceptable<T> =nullptr>
+ size_type max_size()const
+ {
+ return segment(get_map_iterator_for(typeid(T))).template max_size<T>();
+ }
+
+ size_type capacity(const std::type_info& info)const
+ {
+ return segment(get_map_iterator_for(info)).capacity();
+ }
+
+ template<typename T,enable_if_acceptable<T> =nullptr>
+ size_type capacity()const
+ {
+ return segment(get_map_iterator_for(typeid(T))).template capacity<T>();
+ }
+
+ void reserve(size_type n)
+ {
+ for(auto& x:map)x.second.reserve(n);
+ }
+
+ void reserve(const std::type_info& info,size_type n)
+ {
+ segment(get_map_iterator_for(info)).reserve(n);
+ }
+
+ template<typename T,enable_if_acceptable<T> =nullptr>
+ void reserve(size_type n)
+ {
+ /* note this creates the segment if it didn't previously exist */
+
+ segment(get_map_iterator_for<T>()).template reserve<T>(n);
+ }
+
+ void shrink_to_fit()
+ {
+ for(auto& x:map)x.second.shrink_to_fit();
+ }
+
+ void shrink_to_fit(const std::type_info& info)
+ {
+ segment(get_map_iterator_for(info)).shrink_to_fit();
+ }
+
+ template<typename T,enable_if_acceptable<T> =nullptr>
+ void shrink_to_fit()
+ {
+ segment(get_map_iterator_for(typeid(T))).template shrink_to_fit<T>();
+ }
+
+ /* modifiers */
+
+ template<typename T,typename... Args,enable_if_acceptable<T> =nullptr>
+ iterator emplace(Args&&... args)
+ {
+ auto it=get_map_iterator_for<T>();
+ return {
+ it,map.end(),
+ segment(it).template emplace_back<T>(std::forward<Args>(args)...)
+ };
+ }
+
+ template<typename T,typename... Args,enable_if_acceptable<T> =nullptr>
+ iterator emplace_hint(const_iterator hint,Args&&... args)
+ {
+ auto it=get_map_iterator_for<T>();
+ return {
+ it,map.end(),
+ hint.mapit==it? /* hint in segment */
+ segment(it).template emplace<T>(
+ hint.segpos,std::forward<Args>(args)...):
+ segment(it).template emplace_back<T>(std::forward<Args>(args)...)
+ };
+ }
+
+ template<typename T,typename... Args,enable_if_acceptable<T> =nullptr>
+ local_base_iterator
+ emplace_pos(local_base_iterator pos,Args&&... args)
+ {
+ return emplace_pos<T>(
+ const_local_base_iterator{pos},std::forward<Args>(args)...);
+ }
+
+ template<typename T,typename... Args,enable_if_acceptable<T> =nullptr>
+ local_base_iterator
+ emplace_pos(const_local_base_iterator pos,Args&&... args)
+ {
+ BOOST_ASSERT(pos.type_info()==typeid(T));
+ return {
+ pos.mapit,
+ pos.segment().template emplace<T>(pos.base(),std::forward<Args>(args)...)
+ };
+ }
+
+ template<typename T,typename... Args>
+ local_iterator<T>
+ emplace_pos(local_iterator<T> pos,Args&&... args)
+ {
+ return emplace_pos(
+ const_local_iterator<T>{pos},std::forward<Args>(args)...);
+ }
+
+ template<typename T,typename... Args>
+ local_iterator<T>
+ emplace_pos(const_local_iterator<T> pos,Args&&... args)
+ {
+ return {
+ pos.mapit,
+ pos.segment().template emplace<T>(pos.base(),std::forward<Args>(args)...)
+ };
+ }
+
+ template<typename T,enable_if_subtype<T> =nullptr>
+ iterator insert(T&& x)
+ {
+ auto it=get_map_iterator_for(x);
+ return {it,map.end(),push_back(segment(it),std::forward<T>(x))};
+ }
+
+ template<
+ typename T,
+ enable_if_not_same<const_iterator,T> =nullptr,
+ enable_if_subtype<T> =nullptr
+ >
+ iterator insert(const_iterator hint,T&& x)
+ {
+ auto it=get_map_iterator_for(x);
+ return {
+ it,map.end(),
+ hint.mapit==it? /* hint in segment */
+ segment(it).insert(hint.segpos,std::forward<T>(x)):
+ push_back(segment(it),std::forward<T>(x))
+ };
+ }
+
+ template<
+ typename BaseIterator,typename T,
+ enable_if_not_same<local_iterator_impl<BaseIterator>,T> =nullptr,
+ enable_if_subtype<T> =nullptr
+ >
+ nonconst_version<local_iterator_impl<BaseIterator>>
+ insert(local_iterator_impl<BaseIterator> pos,T&& x)
+ {
+ BOOST_ASSERT(pos.type_info()==subtypeid(x));
+ return {
+ pos.mapit,
+ pos.segment().insert(pos.base(),std::forward<T>(x))
+ };
+ }
+
+ template<
+ typename InputIterator,
+ enable_if_derefs_to_subtype<InputIterator> =nullptr,
+ enable_if_derefs_to_not_terminal<InputIterator> =nullptr
+ >
+ void insert(InputIterator first,InputIterator last)
+ {
+ for(;first!=last;++first)insert(*first);
+ }
+
+ template<
+ typename InputIterator,
+ enable_if_derefs_to_subtype<InputIterator> =nullptr,
+ enable_if_derefs_to_terminal<InputIterator> =nullptr
+ >
+ void insert(InputIterator first,InputIterator last)
+ {
+ if(first==last)return;
+
+ /* same segment for all (type is terminal) */
+
+ auto& seg=segment(get_map_iterator_for(*first));
+ seg.insert(first,last);
+ }
+
+ template<bool Const>
+ void insert(iterator_impl<Const> first,iterator_impl<Const> last)
+ {
+ for(;first!=last;++first){
+ auto& seg=segment(get_map_iterator_for(*first,first.segment()));
+ push_back(seg,*first);
+ }
+ }
+
+ template<typename BaseIterator>
+ void insert(
+ local_iterator_impl<BaseIterator> first,
+ local_iterator_impl<BaseIterator> last)
+ {
+ if(first==last)return;
+
+ /* same segment for all (iterator is local) */
+
+ auto& seg=segment(get_map_iterator_for(*first,first.segment()));
+ do seg.push_back(*first); while(++first!=last);
+ }
+
+ template<
+ typename InputIterator,
+ enable_if_derefs_to_subtype<InputIterator> =nullptr,
+ enable_if_derefs_to_not_terminal<InputIterator> =nullptr
+ >
+ void insert(const_iterator hint,InputIterator first,InputIterator last)
+ {
+ for(;first!=last;++first){
+ auto it=get_map_iterator_for(*first);
+ if(hint.mapit==it){ /* hint in segment */
+ hint={it,map.end(),segment(it).insert(hint.segpos,*first)};
+ ++hint;
+ }
+ else push_back(segment(it),*first);
+ }
+ }
+
+ template<
+ typename InputIterator,
+ enable_if_derefs_to_subtype<InputIterator> =nullptr,
+ enable_if_derefs_to_terminal<InputIterator> =nullptr
+ >
+ void insert(const_iterator hint,InputIterator first,InputIterator last)
+ {
+ if(first==last)return;
+
+ /* same segment for all (type is terminal) */
+
+ auto it=get_map_iterator_for(*first);
+ auto& seg=segment(it);
+ if(hint.mapit==it)seg.insert(hint.segpos,first,last); /* hint in segment */
+ else seg.insert(first,last);
+ }
+
+ template<bool Const>
+ void insert(
+ const_iterator hint,iterator_impl<Const> first,iterator_impl<Const> last)
+ {
+ for(;first!=last;++first){
+ auto it=get_map_iterator_for(*first,first.segment());
+ if(hint.mapit==it){ /* hint in segment */
+ hint={it,map.end(),segment(it).insert(hint.segpos,*first)};
+ ++hint;
+ }
+ else push_back(segment(it),*first);
+ }
+ }
+
+ template<typename BaseIterator>
+ void insert(
+ const_iterator hint,
+ local_iterator_impl<BaseIterator> first,
+ local_iterator_impl<BaseIterator> last)
+ {
+ if(first==last)return;
+
+ /* same segment for all (iterator is local) */
+
+ auto it=get_map_iterator_for(*first,first.segment());
+ auto& seg=segment(it);
+ if(hint.mapit==it){ /* hint in segment */
+ do{
+ hint={it,map.end(),seg.insert(hint.segpos,*first)};
+ ++hint;
+ }while(++first!=last);
+ }
+ else{
+ do push_back(seg,*first); while(++first!=last);
+ }
+ }
+
+ template<
+ typename InputIterator,
+ enable_if_derefs_to_subtype<InputIterator> =nullptr
+ >
+ local_base_iterator insert(
+ const_local_base_iterator pos,InputIterator first,InputIterator last)
+ {
+ auto& seg=pos.segment();
+ auto it=Model::nonconst_iterator(pos.base());
+ size_type n=0;
+
+ for(;first!=last;++first){
+ BOOST_ASSERT(pos.type_info()==subtypeid(*first));
+ it=std::next(seg.insert(it,*first));
+ ++n;
+ }
+ return {pos.mapit,it-n};
+ }
+
+ template<typename T,typename InputIterator>
+ local_iterator<T> insert(
+ const_local_iterator<T> pos,InputIterator first,InputIterator last)
+ {
+ auto& seg=pos.segment();
+ segment_iterator<T> it=Model::nonconst_iterator(pos.base());
+ size_type n=0;
+
+ for(;first!=last;++first){
+ it=std::next(
+ static_cast<segment_iterator<T>>(local_insert<T>(seg,it,*first)));
+ ++n;
+ }
+ return {pos.mapit,it-n};
+ }
+
+ template<typename T,typename InputIterator>
+ local_iterator<T> insert(
+ local_iterator<T> pos,InputIterator first,InputIterator last)
+ {
+ return insert(const_local_iterator<T>{pos},first,last);
+ }
+
+ iterator erase(const_iterator pos)
+ {
+ return {pos.mapit,pos.mapend,pos.segment().erase(pos.segpos)};
+ }
+
+ template<typename BaseIterator>
+ nonconst_version<local_iterator_impl<BaseIterator>>
+ erase(local_iterator_impl<BaseIterator> pos)
+ {
+ return {pos.mapit,pos.segment().erase(pos.base())};
+ }
+
+ iterator erase(const_iterator first, const_iterator last)
+ {
+ const_segment_map_iterator fseg=first.mapit,
+ lseg=last.mapit,
+ end=first.mapend;
+
+ if(fseg!=lseg){ /* [first,last] spans over more than one segment */
+ /* from 1st elem to end of 1st segment */
+
+ segment(fseg).erase_till_end(first.segpos);
+
+ /* entire segments till last one */
+
+ while(++fseg!=lseg)segment(fseg).clear();
+
+ /* remaining elements of last segment */
+
+ if(fseg==end){ /* except if at end of container */
+ return {end,end};
+ }
+ else{
+ return {fseg,end,segment(fseg).erase_from_begin(last.segpos)};
+ }
+ }
+ else{ /* range is included in one segment only */
+ if(first==last){ /* to avoid segment(fseg) when fseg==end */
+ return {fseg,end,first.segpos};
+ }
+ else{
+ return {fseg,end,segment(fseg).erase(first.segpos,last.segpos)};
+ }
+ }
+ }
+
+ template<typename BaseIterator>
+ nonconst_version<local_iterator_impl<BaseIterator>>
+ erase(
+ local_iterator_impl<BaseIterator> first,
+ local_iterator_impl<BaseIterator> last)
+ {
+ BOOST_ASSERT(first.mapit==last.mapit);
+ return{
+ first.mapit,
+ first.segment().erase(first.base(),last.base())
+ };
+ }
+
+ void clear()noexcept
+ {
+ for(auto& x:map)x.second.clear();
+ }
+
+ void clear(const std::type_info& info)
+ {
+ segment(get_map_iterator_for(info)).clear();
+ }
+
+ template<typename T,enable_if_acceptable<T> =nullptr>
+ void clear()
+ {
+ segment(get_map_iterator_for(typeid(T))).template clear<T>();
+ }
+
+ void swap(poly_collection& x){map.swap(x.map);}
+
+private:
+ template<typename M,typename A>
+ friend bool operator==(
+ const poly_collection<M,A>&,const poly_collection<M,A>&);
+
+ template<
+ typename T,
+ enable_if_acceptable<T> =nullptr,
+ enable_if_not_terminal<T> =nullptr
+ >
+ const_segment_map_iterator get_map_iterator_for(const T& x)
+ {
+ const auto& id=subtypeid(x);
+ auto it=map.find(id);
+ if(it!=map.end())return it;
+ else if(id!=typeid(T))throw unregistered_type{id};
+ else return map.insert(
+ typeid(T),segment_type::template make<T>(get_allocator())).first;
+ }
+
+ template<
+ typename T,
+ enable_if_acceptable<T> =nullptr,
+ enable_if_terminal<T> =nullptr
+ >
+ const_segment_map_iterator get_map_iterator_for(const T&)
+ {
+ auto it=map.find(typeid(T));
+ if(it!=map.end())return it;
+ else return map.insert(
+ typeid(T),segment_type::template make<T>(get_allocator())).first;
+ }
+
+ template<
+ typename T,
+ enable_if_not_acceptable<T> =nullptr,
+ enable_if_not_terminal<T> =nullptr
+ >
+ const_segment_map_iterator get_map_iterator_for(const T& x)const
+ {
+ const auto& id=subtypeid(x);
+ auto it=map.find(id);
+ if(it!=map.end())return it;
+ else throw unregistered_type{id};
+ }
+
+ template<
+ typename T,
+ enable_if_not_acceptable<T> =nullptr,
+ enable_if_terminal<T> =nullptr
+ >
+ const_segment_map_iterator get_map_iterator_for(const T&)const
+ {
+ static_assert(
+ is_acceptable<T>::value,
+ "type must be move constructible and move assignable");
+ return {}; /* never executed */
+ }
+
+ template<typename T>
+ const_segment_map_iterator get_map_iterator_for(
+ const T& x,const segment_type& seg)
+ {
+ const auto& id=subtypeid(x);
+ auto it=map.find(id);
+ if(it!=map.end())return it;
+ else return map.insert(id,segment_type::make_from_prototype(seg)).first;
+ }
+
+ template<typename T>
+ const_segment_map_iterator get_map_iterator_for()
+ {
+ auto it=map.find(typeid(T));
+ if(it!=map.end())return it;
+ else return map.insert(
+ typeid(T),segment_type::template make<T>(get_allocator())).first;
+ }
+
+ const_segment_map_iterator get_map_iterator_for(const std::type_info& info)
+ {
+ return const_cast<const poly_collection*>(this)->
+ get_map_iterator_for(info);
+ }
+
+ const_segment_map_iterator get_map_iterator_for(
+ const std::type_info& info)const
+ {
+ auto it=map.find(info);
+ if(it!=map.end())return it;
+ else throw unregistered_type{info};
+ }
+
+ static segment_type& segment(const_segment_map_iterator pos)
+ {
+ return const_cast<segment_type&>(pos->second);
+ }
+
+ template<
+ typename T,
+ enable_if_not_acceptable<T> =nullptr
+ >
+ segment_base_iterator push_back(segment_type& seg,T&& x)
+ {
+ return seg.push_back(std::forward<T>(x));
+ }
+
+ template<
+ typename T,
+ enable_if_acceptable<T> =nullptr,
+ enable_if_not_terminal<T> =nullptr
+ >
+ segment_base_iterator push_back(segment_type& seg,T&& x)
+ {
+ return subtypeid(x)==typeid(T)?
+ seg.push_back_terminal(std::forward<T>(x)):
+ seg.push_back(std::forward<T>(x));
+ }
+
+ template<
+ typename T,
+ enable_if_acceptable<T> =nullptr,
+ enable_if_terminal<T> =nullptr
+ >
+ segment_base_iterator push_back(segment_type& seg,T&& x)
+ {
+ return seg.push_back_terminal(std::forward<T>(x));
+ }
+
+ template<
+ typename T,typename BaseIterator,typename U,
+ enable_if_subtype<U> =nullptr,
+ enable_if_not_constructible<T,U&&> =nullptr
+ >
+ static segment_base_iterator local_insert(
+ segment_type& seg,BaseIterator pos,U&& x)
+ {
+ BOOST_ASSERT(subtypeid(x)==typeid(T));
+ return seg.insert(pos,std::forward<U>(x));
+ }
+
+ template<
+ typename T,typename BaseIterator,typename U,
+ enable_if_subtype<U> =nullptr,
+ enable_if_constructible<T,U&&> =nullptr
+ >
+ static segment_base_iterator local_insert(
+ segment_type& seg,BaseIterator pos,U&& x)
+ {
+ if(subtypeid(x)==typeid(T))return seg.insert(pos,std::forward<U>(x));
+ else return seg.template emplace<T>(pos,std::forward<U>(x));
+ }
+
+ template<
+ typename T,typename BaseIterator,typename U,
+ enable_if_not_subtype<U> =nullptr,
+ enable_if_constructible<T,U&&> =nullptr
+ >
+ static segment_base_iterator local_insert(
+ segment_type& seg,BaseIterator pos,U&& x)
+ {
+ return seg.template emplace<T>(pos,std::forward<U>(x));
+ }
+
+ template<
+ typename T,typename BaseIterator,typename U,
+ enable_if_not_subtype<U> =nullptr,
+ enable_if_not_constructible<T,U&&> =nullptr
+ >
+ static segment_base_iterator local_insert(
+ segment_type&,BaseIterator,U&&)
+ {
+ static_assert(
+ is_constructible<T,U&&>::value,
+ "element must be constructible from type");
+ return {}; /* never executed */
+ }
+
+ segment_map map;
+};
+
+template<typename Model,typename Allocator>
+bool operator==(
+ const poly_collection<Model,Allocator>& x,
+ const poly_collection<Model,Allocator>& y)
+{
+ typename poly_collection<Model,Allocator>::size_type s=0;
+ const auto &mapx=x.map,&mapy=y.map;
+ for(const auto& p:mapx){
+ auto ss=p.second.size();
+ auto it=mapy.find(*p.first);
+ if(it==mapy.end()?ss!=0:p.second!=it->second)return false;
+ s+=ss;
+ }
+ return s==y.size();
+}
+
+template<typename Model,typename Allocator>
+bool operator!=(
+ const poly_collection<Model,Allocator>& x,
+ const poly_collection<Model,Allocator>& y)
+{
+ return !(x==y);
+}
+
+template<typename Model,typename Allocator>
+void swap(
+ poly_collection<Model,Allocator>& x,poly_collection<Model,Allocator>& y)
+{
+ x.swap(y);
+}
+
+} /* namespace poly_collection::detail::poly_collection_impl */
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/segment.hpp b/boost/poly_collection/detail/segment.hpp
new file mode 100644
index 0000000000..52aa4d4a66
--- /dev/null
+++ b/boost/poly_collection/detail/segment.hpp
@@ -0,0 +1,296 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_SEGMENT_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_SEGMENT_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <iterator>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* segment<Model,Allocator> encapsulates implementations of
+ * Model::segment_backend virtual interface under a value-semantics type for
+ * use by poly_collection. The techique is described by Sean Parent at slides
+ * 157-205 of
+ * https://github.com/sean-parent/sean-parent.github.com/wiki/
+ * presentations/2013-09-11-cpp-seasoning/cpp-seasoning.pdf
+ * with one twist: when the type of the implementation can be known at compile
+ * time, a downcast is done and non-virtual member functions (named with a nv_
+ * prefix) are used: this increases the performance of some operations.
+ */
+
+template<typename Model,typename Allocator>
+class segment
+{
+public:
+ using value_type=typename Model::value_type;
+ using base_iterator=typename Model::base_iterator;
+ using const_base_iterator=typename Model::const_base_iterator;
+ using base_sentinel=typename Model::base_sentinel;
+ using const_base_sentinel=typename Model::const_base_sentinel;
+ template<typename T>
+ using iterator=typename Model::template iterator<T>;
+ template<typename T>
+ using const_iterator=typename Model::template const_iterator<T>;
+
+ template<typename T>
+ static segment make(const Allocator& al)
+ {
+ return Model::template make<T>(al);
+ }
+
+ /* clones the implementation of x with no elements */
+
+ static segment make_from_prototype(const segment& x)
+ {
+ return {from_prototype{},x};
+ }
+
+ segment(const segment& x):pimpl{x.impl().copy()}{set_sentinel();}
+ segment(segment&& x)=default;
+ segment& operator=(segment x) // TODO: Why do we need this?
+ {
+ pimpl=std::move(x.pimpl);
+ snt=x.snt;
+ return *this;
+ }
+
+ friend bool operator==(const segment& x,const segment& y)
+ {
+ if(typeid(*(x.pimpl))!=typeid(*(y.pimpl)))return false;
+ else return x.impl().equal(y.impl());
+ }
+
+ friend bool operator!=(const segment& x,const segment& y){return !(x==y);}
+
+ base_iterator begin()const noexcept{return impl().begin();}
+ template<typename U>
+ base_iterator begin()const noexcept{return impl<U>().nv_begin();}
+ base_iterator end()const noexcept{return impl().end();}
+ template<typename U>
+ base_iterator end()const noexcept{return impl<U>().nv_end();}
+ base_sentinel sentinel()const noexcept{return snt;}
+ bool empty()const noexcept{return impl().empty();}
+ template<typename U>
+ bool empty()const noexcept{return impl<U>().nv_empty();}
+ std::size_t size()const noexcept{return impl().size();}
+ template<typename U>
+ std::size_t size()const noexcept{return impl<U>().nv_size();}
+ std::size_t max_size()const noexcept{return impl().max_size();}
+ template<typename U>
+ std::size_t max_size()const noexcept
+ {return impl<U>().nv_max_size();}
+ void reserve(std::size_t n){filter(impl().reserve(n));}
+ template<typename U>
+ void reserve(std::size_t n){filter(impl<U>().nv_reserve(n));}
+ std::size_t capacity()const noexcept{return impl().capacity();}
+ template<typename U>
+ std::size_t capacity()const noexcept
+ {return impl<U>().nv_capacity();}
+ void shrink_to_fit(){filter(impl().shrink_to_fit());}
+ template<typename U>
+ void shrink_to_fit(){filter(impl<U>().nv_shrink_to_fit());}
+
+ template<typename U,typename Iterator,typename... Args>
+ base_iterator emplace(Iterator it,Args&&... args)
+ {
+ return filter(impl<U>().nv_emplace(it,std::forward<Args>(args)...));
+ }
+
+ template<typename U,typename... Args>
+ base_iterator emplace_back(Args&&... args)
+ {
+ return filter(impl<U>().nv_emplace_back(std::forward<Args>(args)...));
+ }
+
+ template<typename T>
+ base_iterator push_back(const T& x)
+ {
+ return filter(impl().push_back(subaddress(x)));
+ }
+
+ template<
+ typename T,
+ typename std::enable_if<
+ !std::is_lvalue_reference<T>::value&&!std::is_const<T>::value
+ >::type* =nullptr
+ >
+ base_iterator push_back(T&& x)
+ {
+ return filter(impl().push_back_move(subaddress(x)));
+ }
+
+ template<typename U>
+ base_iterator push_back_terminal(U&& x)
+ {
+ return filter(
+ impl<typename std::decay<U>::type>().nv_push_back(std::forward<U>(x)));
+ }
+
+ template<typename T>
+ base_iterator insert(const_base_iterator it,const T& x)
+ {
+ return filter(impl().insert(it,subaddress(x)));
+ }
+
+ template<typename U,typename T>
+ base_iterator insert(const_iterator<U> it,const T& x)
+ {
+ return filter(
+ impl<U>().nv_insert(it,*static_cast<const U*>(subaddress(x))));
+ }
+
+ template<
+ typename T,
+ typename std::enable_if<
+ !std::is_lvalue_reference<T>::value&&!std::is_const<T>::value
+ >::type* =nullptr
+ >
+ base_iterator insert(const_base_iterator it,T&& x)
+ {
+ return filter(impl().insert_move(it,subaddress(x)));
+ }
+
+ template<
+ typename U,typename T,
+ typename std::enable_if<
+ !std::is_lvalue_reference<T>::value&&!std::is_const<T>::value
+ >::type* =nullptr
+ >
+ base_iterator insert(const_iterator<U> it,T&& x)
+ {
+ return filter(
+ impl<U>().nv_insert(it,std::move(*static_cast<U*>(subaddress(x)))));
+ }
+
+ template<typename InputIterator>
+ base_iterator insert(InputIterator first,InputIterator last)
+ {
+ return filter(
+ impl<typename std::iterator_traits<InputIterator>::value_type>().
+ nv_insert(first,last));
+ }
+
+ template<typename InputIterator>
+ base_iterator insert(
+ const_base_iterator it,InputIterator first,InputIterator last)
+ {
+ return insert(
+ const_iterator<
+ typename std::iterator_traits<InputIterator>::value_type>(it),
+ first,last);
+ }
+
+ template<typename U,typename InputIterator>
+ base_iterator insert(
+ const_iterator<U> it,InputIterator first,InputIterator last)
+ {
+ return filter(impl<U>().nv_insert(it,first,last));
+ }
+
+ base_iterator erase(const_base_iterator it)
+ {
+ return filter(impl().erase(it));
+ }
+
+ template<typename U>
+ base_iterator erase(const_iterator<U> it)
+ {
+ return filter(impl<U>().nv_erase(it));
+ }
+
+ base_iterator erase(const_base_iterator f,const_base_iterator l)
+ {
+ return filter(impl().erase(f,l));
+ }
+
+ template<typename U>
+ base_iterator erase(const_iterator<U> f,const_iterator<U> l)
+ {
+ return filter(impl<U>().nv_erase(f,l));
+ }
+
+ template<typename Iterator>
+ base_iterator erase_till_end(Iterator f)
+ {
+ return filter(impl().erase_till_end(f));
+ }
+
+ template<typename Iterator>
+ base_iterator erase_from_begin(Iterator l)
+ {
+ return filter(impl().erase_from_begin(l));
+ }
+
+ void clear()noexcept{filter(impl().clear());}
+ template<typename U>
+ void clear()noexcept{filter(impl<U>().nv_clear());}
+
+private:
+ using segment_backend=typename Model::segment_backend;
+ template<typename Concrete>
+ using segment_backend_implementation=typename Model::
+ template segment_backend_implementation<Concrete,Allocator>;
+ using segment_backend_unique_ptr=
+ typename segment_backend::segment_backend_unique_ptr;
+ using range=typename segment_backend::range;
+
+ struct from_prototype{};
+
+ segment(segment_backend_unique_ptr&& pimpl):
+ pimpl{std::move(pimpl)}{set_sentinel();}
+ segment(from_prototype,const segment& x):
+ pimpl{x.impl().empty_copy()}{set_sentinel();}
+
+ segment_backend& impl()noexcept{return *pimpl;}
+ const segment_backend& impl()const noexcept{return *pimpl;}
+
+ template<typename Concrete>
+ segment_backend_implementation<Concrete>& impl()noexcept
+ {
+ return static_cast<segment_backend_implementation<Concrete>&>(impl());
+ }
+
+ template<typename Concrete>
+ const segment_backend_implementation<Concrete>& impl()const noexcept
+ {
+ return
+ static_cast<const segment_backend_implementation<Concrete>&>(impl());
+ }
+
+ template<typename T>
+ static void* subaddress(T& x){return Model::subaddress(x);}
+ template<typename T>
+ static const void* subaddress(const T& x){return Model::subaddress(x);}
+
+ void set_sentinel(){filter(impl().end());}
+ void filter(base_sentinel x){snt=x;}
+ base_iterator filter(const range& x){snt=x.second;return x.first;}
+
+ segment_backend_unique_ptr pimpl;
+ base_sentinel snt;
+};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/segment_backend.hpp b/boost/poly_collection/detail/segment_backend.hpp
new file mode 100644
index 0000000000..f097ac2edc
--- /dev/null
+++ b/boost/poly_collection/detail/segment_backend.hpp
@@ -0,0 +1,82 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_SEGMENT_BACKEND_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_SEGMENT_BACKEND_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <cstddef>
+#include <memory>
+#include <utility>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* Internal *virtual* interface of segment<Model,Allocator> (please note that
+ * a non-virtual interface exists accessible thrown downcasting). Member
+ * functions have been defined to minimize virtual function calls according to
+ * usage patterns by poly_collection. For instance, ranges are returned rather
+ * than iterators to allow for caching of and end sentinel at a higher level.
+ * Passed elements are type erased with [const_]value_pointer.
+ */
+
+template<typename Model>
+struct segment_backend
+{
+ using segment_backend_unique_ptr=
+ std::unique_ptr<segment_backend,void(*)(segment_backend*)>;
+ using value_pointer=void*;
+ using const_value_pointer=const void*;
+ using base_iterator=typename Model::base_iterator;
+ using const_base_iterator=typename Model::const_base_iterator;
+ template<typename T>
+ using const_iterator=typename Model::template const_iterator<T>;
+ using base_sentinel=typename Model::base_sentinel;
+ using range=std::pair<base_iterator,base_sentinel>;
+
+ segment_backend()=default;
+ segment_backend(const segment_backend&)=delete;
+ segment_backend& operator=(const segment_backend&)=delete;
+
+ virtual ~segment_backend()=default;
+ virtual segment_backend_unique_ptr copy()const=0;
+ virtual segment_backend_unique_ptr empty_copy()const=0;
+ virtual bool equal(const segment_backend&)const=0;
+
+ virtual base_iterator begin()const noexcept=0;
+ virtual base_iterator end()const noexcept=0;
+ virtual bool empty()const noexcept=0;
+ virtual std::size_t size()const noexcept=0;
+ virtual std::size_t max_size()const noexcept=0;
+ virtual std::size_t capacity()const noexcept=0;
+ virtual base_sentinel reserve(std::size_t)=0;
+ virtual base_sentinel shrink_to_fit()=0;
+ virtual range push_back(const_value_pointer)=0;
+ virtual range push_back_move(value_pointer)=0;
+ virtual range insert(const_base_iterator,const_value_pointer)=0;
+ virtual range insert_move(const_base_iterator,value_pointer)=0;
+ virtual range erase(const_base_iterator)=0;
+ virtual range erase(const_base_iterator,const_base_iterator)=0;
+ virtual range erase_till_end(const_base_iterator)=0;
+ virtual range erase_from_begin(const_base_iterator)=0;
+ virtual base_sentinel clear()noexcept=0;
+};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/segment_split.hpp b/boost/poly_collection/detail/segment_split.hpp
new file mode 100644
index 0000000000..8c8efb19b1
--- /dev/null
+++ b/boost/poly_collection/detail/segment_split.hpp
@@ -0,0 +1,154 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_SEGMENT_SPLIT_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_SEGMENT_SPLIT_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/poly_collection/detail/iterator_traits.hpp>
+#include <typeinfo>
+#include <utility>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* breakdown of an iterator range into local_base_iterator segments */
+
+template<typename PolyCollectionIterator>
+class segment_splitter
+{
+ using traits=iterator_traits<PolyCollectionIterator>;
+ using local_base_iterator=typename traits::local_base_iterator;
+ using base_segment_info_iterator=typename traits::base_segment_info_iterator;
+
+public:
+ struct info
+ {
+ const std::type_info& type_info()const noexcept{return *pinfo_;}
+ local_base_iterator begin()const noexcept{return begin_;}
+ local_base_iterator end()const noexcept{return end_;}
+
+ const std::type_info* pinfo_;
+ local_base_iterator begin_,end_;
+ };
+
+ struct iterator:iterator_facade<iterator,info,std::input_iterator_tag,info>
+ {
+ iterator()=default;
+
+ private:
+ friend class segment_splitter;
+ friend class boost::iterator_core_access;
+
+ iterator(
+ base_segment_info_iterator it,
+ const PolyCollectionIterator& first,const PolyCollectionIterator& last):
+ it{it},first{&first},last{&last}{}
+ iterator(
+ const PolyCollectionIterator& first,const PolyCollectionIterator& last):
+ it{traits::base_segment_info_iterator_from(first)},
+ first{&first},last{&last}
+ {}
+
+ info dereference()const noexcept
+ {
+ return {
+ &it->type_info(),
+ it==traits::base_segment_info_iterator_from(*first)?
+ traits::local_base_iterator_from(*first):it->begin(),
+ it==traits::base_segment_info_iterator_from(*last)?
+ traits::local_base_iterator_from(*last):it->end()
+ };
+ }
+
+ bool equal(const iterator& x)const noexcept{return it==x.it;}
+ void increment()noexcept{++it;}
+
+ base_segment_info_iterator it;
+ const PolyCollectionIterator* first;
+ const PolyCollectionIterator* last;
+ };
+
+ segment_splitter(
+ const PolyCollectionIterator& first,const PolyCollectionIterator& last):
+ first{first},last{last}{}
+
+ iterator begin()const noexcept{return {first,last};}
+
+ iterator end()const noexcept
+ {
+ auto slast=traits::base_segment_info_iterator_from(last);
+ if(slast!=traits::end_base_segment_info_iterator_from(last))++slast;
+ return {slast,last,last};
+ }
+
+private:
+ const PolyCollectionIterator& first;
+ const PolyCollectionIterator& last;
+};
+
+template<typename PolyCollectionIterator>
+segment_splitter<PolyCollectionIterator>
+segment_split(
+ const PolyCollectionIterator& first,const PolyCollectionIterator& last)
+{
+ return {first,last};
+}
+
+#if 1
+/* equivalent to for(auto i:segment_split(first,last))f(i) */
+
+template<typename PolyCollectionIterator,typename F>
+void for_each_segment(
+ const PolyCollectionIterator& first,const PolyCollectionIterator& last,F&& f)
+{
+ using traits=iterator_traits<PolyCollectionIterator>;
+ using info=typename segment_splitter<PolyCollectionIterator>::info;
+
+ auto sfirst=traits::base_segment_info_iterator_from(first),
+ slast=traits::base_segment_info_iterator_from(last),
+ send=traits::end_base_segment_info_iterator_from(last);
+ auto lbfirst=traits::local_base_iterator_from(first),
+ lblast=traits::local_base_iterator_from(last);
+
+ if(sfirst!=slast){
+ for(;;){
+ f(info{&sfirst->type_info(),lbfirst,sfirst->end()});
+ ++sfirst;
+ if(sfirst==slast)break;
+ lbfirst=sfirst->begin();
+ }
+ if(sfirst!=send)f(info{&sfirst->type_info(),sfirst->begin(),lblast});
+ }
+ else if(sfirst!=send){
+ f(info{&sfirst->type_info(),lbfirst,lblast});
+ }
+}
+#else
+template<typename PolyCollectionIterator,typename F>
+void for_each_segment(
+ const PolyCollectionIterator& first,const PolyCollectionIterator& last,F&& f)
+{
+ for(auto i:segment_split(first,last))f(i);
+}
+#endif
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/split_segment.hpp b/boost/poly_collection/detail/split_segment.hpp
new file mode 100644
index 0000000000..5fc9e11e20
--- /dev/null
+++ b/boost/poly_collection/detail/split_segment.hpp
@@ -0,0 +1,487 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_SPLIT_SEGMENT_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_SPLIT_SEGMENT_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/poly_collection/detail/newdelete_allocator.hpp>
+#include <boost/poly_collection/detail/segment_backend.hpp>
+#include <boost/poly_collection/detail/value_holder.hpp>
+#include <iterator>
+#include <memory>
+#include <new>
+#include <utility>
+#include <vector>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* segment_backend implementation that maintains two internal vectors, one for
+ * value_type's (the index) and another for the concrete elements those refer
+ * to (the store).
+ *
+ * Requires:
+ * - [const_]base_iterator is constructible from value_type*.
+ * - value_type is copy constructible.
+ * - Model::make_value_type(x) returns a value_type created from a reference
+ * to the concrete type.
+ *
+ * Conversion from base_iterator to local_iterator<Concrete> requires accesing
+ * value_type internal info, so the end() base_iterator has to be made to point
+ * to a valid element of index, which implies size(index)=size(store)+1. This
+ * slightly complicates the memory management.
+ */
+
+template<typename Model,typename Concrete,typename Allocator>
+class split_segment:public segment_backend<Model>
+{
+ using value_type=typename Model::value_type;
+ using store_value_type=value_holder<Concrete>;
+ using store=std::vector<
+ store_value_type,
+ value_holder_allocator_adaptor<
+ typename std::allocator_traits<Allocator>::
+ template rebind_alloc<store_value_type>
+ >
+ >;
+ using store_iterator=typename store::iterator;
+ using const_store_iterator=typename store::const_iterator;
+ using index=std::vector<
+ value_type,
+ newdelete_allocator_adaptor<
+ typename std::allocator_traits<Allocator>::
+ template rebind_alloc<value_type>
+ >
+ >;
+ using const_index_iterator=typename index::const_iterator;
+ using segment_backend=detail::segment_backend<Model>;
+ using typename segment_backend::segment_backend_unique_ptr;
+ using typename segment_backend::value_pointer;
+ using typename segment_backend::const_value_pointer;
+ using typename segment_backend::base_iterator;
+ using typename segment_backend::const_base_iterator;
+ using const_iterator=
+ typename segment_backend::template const_iterator<Concrete>;
+ using typename segment_backend::base_sentinel;
+ using typename segment_backend::range;
+ using segment_allocator_type=newdelete_allocator_adaptor<
+ typename std::allocator_traits<Allocator>::
+ template rebind_alloc<split_segment>
+ >;
+
+public:
+ virtual ~split_segment()=default;
+
+ virtual segment_backend_unique_ptr copy()const
+ {
+ return new_(s.get_allocator(),store{s});
+ }
+
+ virtual segment_backend_unique_ptr empty_copy()const
+ {
+ return new_(s.get_allocator(),s.get_allocator());
+ }
+
+ virtual bool equal(const segment_backend& x)const
+ {
+ return s==static_cast<const split_segment&>(x).s;
+ }
+
+ virtual base_iterator begin()const noexcept{return nv_begin();}
+ base_iterator nv_begin()const noexcept
+ {return base_iterator{value_ptr(i.data())};}
+ virtual base_iterator end()const noexcept{return nv_end();}
+ base_iterator nv_end()const noexcept
+ {return base_iterator{value_ptr(i.data()+s.size())};}
+ virtual bool empty()const noexcept{return nv_empty();}
+ bool nv_empty()const noexcept{return s.empty();}
+ virtual std::size_t size()const noexcept{return nv_size();}
+ std::size_t nv_size()const noexcept{return s.size();}
+ virtual std::size_t max_size()const noexcept{return nv_max_size();}
+ std::size_t nv_max_size()const noexcept{return s.max_size()-1;}
+ virtual std::size_t capacity()const noexcept{return nv_capacity();}
+ std::size_t nv_capacity()const noexcept{return s.capacity();}
+
+ virtual base_sentinel reserve(std::size_t n){return nv_reserve(n);}
+
+ base_sentinel nv_reserve(std::size_t n)
+ {
+ bool rebuild=n>s.capacity();
+ i.reserve(n+1);
+ s.reserve(n);
+ if(rebuild)rebuild_index();
+ return sentinel();
+ };
+
+ virtual base_sentinel shrink_to_fit(){return nv_shrink_to_fit();}
+
+ base_sentinel nv_shrink_to_fit()
+ {
+ auto p=s.data();
+ s.shrink_to_fit();
+ if(p!=s.data())try{
+ index ii{{},i.get_allocator()};
+ ii.reserve(s.capacity()+1);
+ i.swap(ii);
+ build_index();
+ }
+ catch(...){
+ rebuild_index();
+ throw;
+ }
+ return sentinel();
+ }
+
+ template<typename Iterator,typename... Args>
+ range nv_emplace(Iterator p,Args&&... args)
+ {
+ auto q=prereserve(p);
+ auto it=s.emplace(
+ iterator_from(q),
+ value_holder_emplacing_ctor,std::forward<Args>(args)...);
+ push_index_entry();
+ return range_from(it);
+ }
+
+ template<typename... Args>
+ range nv_emplace_back(Args&&... args)
+ {
+ prereserve();
+ s.emplace_back(value_holder_emplacing_ctor,std::forward<Args>(args)...);
+ push_index_entry();
+ return range_from(s.size()-1);
+ }
+
+ virtual range push_back(const_value_pointer x)
+ {return nv_push_back(const_concrete_ref(x));}
+
+ range nv_push_back(const Concrete& x)
+ {
+ prereserve();
+ s.emplace_back(x);
+ push_index_entry();
+ return range_from(s.size()-1);
+ }
+
+ virtual range push_back_move(value_pointer x)
+ {return nv_push_back(std::move(concrete_ref(x)));}
+
+ range nv_push_back(Concrete&& x)
+ {
+ prereserve();
+ s.emplace_back(std::move(x));
+ push_index_entry();
+ return range_from(s.size()-1);
+ }
+
+ virtual range insert(const_base_iterator p,const_value_pointer x)
+ {return nv_insert(const_iterator(p),const_concrete_ref(x));}
+
+ range nv_insert(const_iterator p,const Concrete& x)
+ {
+ p=prereserve(p);
+ auto it=s.emplace(iterator_from(p),x);
+ push_index_entry();
+ return range_from(it);
+ }
+
+ virtual range insert_move(const_base_iterator p,value_pointer x)
+ {return nv_insert(const_iterator(p),std::move(concrete_ref(x)));}
+
+ range nv_insert(const_iterator p,Concrete&& x)
+ {
+ p=prereserve(p);
+ auto it=s.emplace(iterator_from(p),std::move(x));
+ push_index_entry();
+ return range_from(it);
+ }
+
+ template<typename InputIterator>
+ range nv_insert(InputIterator first,InputIterator last)
+ {
+ return nv_insert(
+ const_iterator(concrete_ptr(s.data()+s.size())),first,last);
+ }
+
+ template<typename InputIterator>
+ range nv_insert(const_iterator p,InputIterator first,InputIterator last)
+ {
+ return insert(
+ p,first,last,
+ typename std::iterator_traits<InputIterator>::iterator_category{});
+ }
+
+ virtual range erase(const_base_iterator p)
+ {return nv_erase(const_iterator(p));}
+
+ range nv_erase(const_iterator p)
+ {
+ pop_index_entry();
+ return range_from(s.erase(iterator_from(p)));
+ }
+
+ virtual range erase(const_base_iterator first,const_base_iterator last)
+ {return nv_erase(const_iterator(first),const_iterator(last));}
+
+ range nv_erase(const_iterator first,const_iterator last)
+ {
+ std::size_t n=s.size();
+ auto it=s.erase(iterator_from(first),iterator_from(last));
+ pop_index_entry(n-s.size());
+ return range_from(it);
+ }
+
+ virtual range erase_till_end(const_base_iterator first)
+ {
+ std::size_t n=s.size();
+ auto it=s.erase(iterator_from(first),s.end());
+ pop_index_entry(n-s.size());
+ return range_from(it);
+ }
+
+ virtual range erase_from_begin(const_base_iterator last)
+ {
+ std::size_t n=s.size();
+ auto it=s.erase(s.begin(),iterator_from(last));
+ pop_index_entry(n-s.size());
+ return range_from(it);
+ }
+
+ base_sentinel clear()noexcept{return nv_clear();}
+
+ base_sentinel nv_clear()noexcept
+ {
+ s.clear();
+ for(std::size_t n=i.size()-1;n--;)i.pop_back();
+ return sentinel();
+ }
+
+private:
+ friend Model;
+
+ template<typename... Args>
+ static segment_backend_unique_ptr new_(
+ segment_allocator_type al,Args&&... args)
+ {
+ auto p=std::allocator_traits<segment_allocator_type>::allocate(al,1);
+ try{
+ ::new ((void*)p) split_segment{std::forward<Args>(args)...};
+ }
+ catch(...){
+ std::allocator_traits<segment_allocator_type>::deallocate(al,p,1);
+ throw;
+ }
+ return {p,&delete_};
+ }
+
+ static void delete_(segment_backend* p)
+ {
+ auto q=static_cast<split_segment*>(p);
+ auto al=segment_allocator_type{q->s.get_allocator()};
+ q->~split_segment();
+ std::allocator_traits<segment_allocator_type>::deallocate(al,q,1);
+ }
+
+ split_segment(const Allocator& al):
+ s{typename store::allocator_type{al}},
+ i{{},typename index::allocator_type{al}}{build_index();}
+ split_segment(store&& s_):
+ s{std::move(s_)},i{{},typename index::allocator_type{s.get_allocator()}}
+ {build_index();}
+
+ void prereserve()
+ {
+ if(s.size()==s.capacity())expand();
+ }
+
+ const_base_iterator prereserve(const_base_iterator p)
+ {
+ if(s.size()==s.capacity()){
+ auto n=p-i.data();
+ expand();
+ return const_base_iterator{i.data()+n};
+ }
+ else return p;
+ }
+
+ const_iterator prereserve(const_iterator p)
+ {
+ if(s.size()==s.capacity()){
+ auto n=p-const_concrete_ptr(s.data());
+ expand();
+ return const_concrete_ptr(s.data())+n;
+ }
+ else return p;
+ }
+
+ const_iterator prereserve(const_iterator p,std::size_t m)
+ {
+ if(s.size()+m>s.capacity()){
+ auto n=p-const_concrete_ptr(s.data());
+ expand(m);
+ return const_concrete_ptr(s.data())+n;
+ }
+ else return p;
+ }
+
+ void expand()
+ {
+ std::size_t c=
+ s.size()<=1||(s.max_size()-1-s.size())/2<s.size()?
+ s.size()+1:
+ s.size()+s.size()/2;
+ i.reserve(c+1);
+ s.reserve(c);
+ rebuild_index();
+ }
+
+ void expand(std::size_t m)
+ {
+ i.reserve(s.size()+m+1);
+ s.reserve(s.size()+m);
+ rebuild_index();
+ }
+
+ void build_index(std::size_t start=0)
+ {
+ for(std::size_t n=start,m=s.size();n<=m;++n){
+ i.push_back(Model::make_value_type(concrete_ref(s.data()[n])));
+ };
+ }
+
+ void rebuild_index()
+ {
+ i.clear();
+ build_index();
+ }
+
+ void push_index_entry()
+ {
+ build_index(s.size());
+ }
+
+ void pop_index_entry(std::size_t n=1)
+ {
+ while(n--)i.pop_back();
+ }
+
+ static Concrete& concrete_ref(value_pointer p)noexcept
+ {
+ return *static_cast<Concrete*>(p);
+ }
+
+ static Concrete& concrete_ref(store_value_type& r)noexcept
+ {
+ return *concrete_ptr(&r);
+ }
+
+ static const Concrete& const_concrete_ref(const_value_pointer p)noexcept
+ {
+ return *static_cast<const Concrete*>(p);
+ }
+
+ static Concrete* concrete_ptr(store_value_type* p)noexcept
+ {
+ return reinterpret_cast<Concrete*>(
+ static_cast<value_holder_base<Concrete>*>(p));
+ }
+
+ static const Concrete* const_concrete_ptr(const store_value_type* p)noexcept
+ {
+ return concrete_ptr(const_cast<store_value_type*>(p));
+ }
+
+ static value_type* value_ptr(const value_type* p)noexcept
+ {
+ return const_cast<value_type*>(p);
+ }
+
+ /* It would have sufficed if iterator_from returned const_store_iterator
+ * except for the fact that some old versions of libstdc++ claiming to be
+ * C++11 compliant do not however provide std::vector modifier ops taking
+ * const_iterator's.
+ */
+
+ store_iterator iterator_from(const_base_iterator p)
+ {
+ return s.begin()+(p-i.data());
+ }
+
+ store_iterator iterator_from(const_iterator p)
+ {
+ return s.begin()+(p-const_concrete_ptr(s.data()));
+ }
+
+ base_sentinel sentinel()const noexcept
+ {
+ return base_iterator{value_ptr(i.data()+s.size())};
+ }
+
+ range range_from(const_store_iterator it)const
+ {
+ return {base_iterator{value_ptr(i.data()+(it-s.begin()))},sentinel()};
+ }
+
+ range range_from(std::size_t n)const
+ {
+ return {base_iterator{value_ptr(i.data()+n)},sentinel()};
+ }
+
+ template<typename InputIterator>
+ range insert(
+ const_iterator p,InputIterator first,InputIterator last,
+ std::input_iterator_tag)
+ {
+ std::size_t n=0;
+ for(;first!=last;++first,++n,++p){
+ p=prereserve(p);
+ s.emplace(iterator_from(p),*first);
+ push_index_entry();
+ }
+ return range_from(iterator_from(p-n));
+ }
+
+ template<typename InputIterator>
+ range insert(
+ const_iterator p,InputIterator first,InputIterator last,
+ std::forward_iterator_tag)
+ {
+ auto n=s.size();
+ auto m=static_cast<std::size_t>(std::distance(first,last));
+ if(m){
+ p=prereserve(p,m);
+ try{
+ s.insert(iterator_from(p),first,last);
+ }
+ catch(...){
+ build_index(n+1);
+ throw;
+ }
+ build_index(n+1);
+ }
+ return range_from(iterator_from(p));
+ }
+
+ store s;
+ index i;
+};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/stride_iterator.hpp b/boost/poly_collection/detail/stride_iterator.hpp
new file mode 100644
index 0000000000..7312e66675
--- /dev/null
+++ b/boost/poly_collection/detail/stride_iterator.hpp
@@ -0,0 +1,123 @@
+/* Copyright 2016 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_STRIDE_ITERATOR_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_STRIDE_ITERATOR_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/iterator/iterator_facade.hpp>
+#include <type_traits>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* random-access iterator to Value elements laid out stride *chars* apart */
+
+template<typename Value>
+class stride_iterator:
+ public boost::iterator_facade<
+ stride_iterator<Value>,
+ Value,
+ boost::random_access_traversal_tag
+ >
+{
+public:
+ stride_iterator()=default;
+ stride_iterator(Value* p,std::size_t stride)noexcept:p{p},stride_{stride}{}
+ stride_iterator(const stride_iterator&)=default;
+ stride_iterator& operator=(const stride_iterator&)=default;
+
+ template<
+ typename NonConstValue,
+ typename std::enable_if<
+ std::is_same<Value,const NonConstValue>::value>::type* =nullptr
+ >
+ stride_iterator(const stride_iterator<NonConstValue>& x)noexcept:
+ p{x.p},stride_{x.stride_}{}
+
+ template<
+ typename NonConstValue,
+ typename std::enable_if<
+ std::is_same<Value,const NonConstValue>::value>::type* =nullptr
+ >
+ stride_iterator& operator=(const stride_iterator<NonConstValue>& x)noexcept
+ {
+ p=x.p;stride_=x.stride_;
+ return *this;
+ }
+
+ /* interoperability with [Derived]Value* */
+
+ stride_iterator& operator=(Value* p_)noexcept{p=p_;return *this;}
+ operator Value*()const noexcept{return p;}
+
+ template<
+ typename DerivedValue,
+ typename std::enable_if<
+ std::is_base_of<Value,DerivedValue>::value&&
+ (std::is_const<Value>::value||!std::is_const<DerivedValue>::value)
+ >::type* =nullptr
+ >
+ explicit stride_iterator(DerivedValue* x)noexcept:
+ p{x},stride_{sizeof(DerivedValue)}{}
+
+ template<
+ typename DerivedValue,
+ typename std::enable_if<
+ std::is_base_of<Value,DerivedValue>::value&&
+ (!std::is_const<Value>::value||std::is_const<DerivedValue>::value)
+ >::type* =nullptr
+ >
+ explicit operator DerivedValue*()const noexcept
+ {return static_cast<DerivedValue*>(p);}
+
+ std::size_t stride()const noexcept{return stride_;}
+
+private:
+ template<typename>
+ friend class stride_iterator;
+
+ using char_pointer=typename std::conditional<
+ std::is_const<Value>::value,
+ const char*,
+ char*
+ >::type;
+
+ static char_pointer char_ptr(Value* p)noexcept
+ {return reinterpret_cast<char_pointer>(p);}
+ static Value* value_ptr(char_pointer p)noexcept
+ {return reinterpret_cast<Value*>(p);}
+
+ friend class boost::iterator_core_access;
+
+ Value& dereference()const noexcept{return *p;}
+ bool equal(const stride_iterator& x)const noexcept{return p==x.p;}
+ void increment()noexcept{p=value_ptr(char_ptr(p)+stride_);}
+ void decrement()noexcept{p=value_ptr(char_ptr(p)-stride_);}
+ template<typename Integral>
+ void advance(Integral n)noexcept{p=value_ptr(char_ptr(p)+n*stride_);}
+ std::ptrdiff_t distance_to(const stride_iterator& x)const noexcept
+ {return (char_ptr(x.p)-char_ptr(p))/stride_;}
+
+ Value* p;
+ std::size_t stride_;
+};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/type_info_map.hpp b/boost/poly_collection/detail/type_info_map.hpp
new file mode 100644
index 0000000000..289af10adb
--- /dev/null
+++ b/boost/poly_collection/detail/type_info_map.hpp
@@ -0,0 +1,169 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_TYPE_INFO_MAP_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_TYPE_INFO_MAP_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/poly_collection/detail/newdelete_allocator.hpp>
+#include <functional>
+#include <typeinfo>
+#include <unordered_map>
+#include <utility>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* To cope with dynamic modules/libs, the standard allows for different
+ * std::type_info instances to describe the same type, which implies that
+ * std::type_info::operator== and std::type_info::hash_code are costly
+ * operations typically relying on the stored type name.
+ * type_info_ptr_hash<T> behaves roughly as a
+ * std::unordered_map<std::type_index,T> but maintains an internal cache of
+ * passed std::type_info instances so that lookup is performed (when there's a
+ * cache hit) without invoking std::type_info equality and hashing ops.
+ */
+
+struct type_info_ptr_hash
+{
+ std::size_t operator()(const std::type_info* p)const noexcept
+ {return p->hash_code();}
+};
+
+struct type_info_ptr_equal_to
+{
+ bool operator()(
+ const std::type_info* p,const std::type_info* q)const noexcept
+ {return *p==*q;}
+};
+
+
+template<typename T,typename Allocator>
+class type_info_map
+{
+ using map_type=std::unordered_map<
+ const std::type_info*,T,
+ type_info_ptr_hash,type_info_ptr_equal_to,
+ typename std::allocator_traits<Allocator>::template
+ rebind_alloc<std::pair<const std::type_info* const,T>>
+ >;
+
+public:
+ using key_type=std::type_info;
+ using mapped_type=T;
+ using value_type=typename map_type::value_type;
+ using allocator_type=typename map_type::allocator_type;
+ using iterator=typename map_type::iterator;
+ using const_iterator=typename map_type::const_iterator;
+
+ type_info_map()=default;
+ type_info_map(const type_info_map& x):
+ map{x.map},cache{x.cache.get_allocator()}{build_cache(x.cache);}
+ type_info_map(type_info_map&& x)=default;
+ type_info_map(const allocator_type& al):
+ map{al},cache{cache_allocator_type{al}}{}
+ type_info_map(const type_info_map& x,const allocator_type& al):
+ map{x.map,al},cache{cache_allocator_type{al}}{build_cache(x.cache);}
+ type_info_map(type_info_map&& x,const allocator_type& al):
+ map{std::move(x.map),al},cache{cache_allocator_type{al}}
+ {
+ if(al==x.map.get_allocator()&&
+ cache_allocator_type{al}==x.cache.get_allocator()){
+ cache=std::move(x.cache);
+ }
+ else{
+ build_cache(x.cache);
+ x.cache.clear();
+ }
+ }
+
+ type_info_map& operator=(const type_info_map& x)
+ {
+ if(this!=&x){
+ type_info_map c{x};
+ swap(c);
+ }
+ return *this;
+ }
+
+ type_info_map& operator=(type_info_map&& x)=default;
+
+ allocator_type get_allocator()const noexcept{return map.get_allocator();}
+
+ iterator begin()noexcept{return map.begin();}
+ iterator end()noexcept{return map.end();}
+ const_iterator begin()const noexcept{return map.begin();}
+ const_iterator end()const noexcept{return map.end();}
+ const_iterator cbegin()const noexcept{return map.cbegin();}
+ const_iterator cend()const noexcept{return map.cend();}
+
+ iterator find(const key_type& key)
+ {
+ auto cit=cache.find(&key);
+ if(cit!=cache.end())return cit->second;
+ auto mit=map.find(&key);
+ if(mit!=map.end())cache.insert({&key,mit});
+ return mit;
+ }
+
+ const_iterator find(const key_type& key)const
+ {
+ auto cit=cache.find(&key);
+ if(cit!=cache.end())return cit->second;
+ return map.find(&key);
+ }
+
+ template<typename P>
+ std::pair<iterator,bool> insert(const key_type& key,P&& x)
+ {
+ auto p=map.insert({&key,std::forward<P>(x)});
+ cache.insert({&key,p.first});
+ return p;
+ }
+
+ void swap(type_info_map& x){map.swap(x.map);cache.swap(x.cache);}
+
+private:
+ using cache_type=std::unordered_map<
+ const std::type_info*,iterator,
+ std::hash<const std::type_info*>,std::equal_to<const std::type_info*>,
+ newdelete_allocator_adaptor<
+ typename std::allocator_traits<Allocator>::template
+ rebind_alloc<std::pair<const std::type_info* const,iterator>>
+ >
+ >;
+ using cache_allocator_type=typename cache_type::allocator_type;
+
+ void build_cache(const cache_type& x)
+ {
+ for(const auto& p:x)cache.insert({p.first,map.find(p.first)});
+ }
+
+ map_type map;
+ cache_type cache;
+};
+
+template<typename T,typename Allocator>
+void swap(type_info_map<T,Allocator>& x,type_info_map<T,Allocator>& y)
+{
+ x.swap(y);
+}
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/type_restitution.hpp b/boost/poly_collection/detail/type_restitution.hpp
new file mode 100644
index 0000000000..dadd96507b
--- /dev/null
+++ b/boost/poly_collection/detail/type_restitution.hpp
@@ -0,0 +1,199 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_TYPE_RESTITUTION_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_TYPE_RESTITUTION_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/poly_collection/detail/functional.hpp>
+#include <boost/poly_collection/detail/iterator_traits.hpp>
+#include <typeinfo>
+#include <utility>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* Given types Ts..., a const std::type_info& info and a local_base_iterator
+ * it, we denote by restitute<Ts...>(info,it):
+ * - a local_iterator<Ti> from it, if info==typeid(Ti) for some Ti in Ts...
+ * - it otherwise.
+ *
+ * Using this notation, restitute_range<Ts...>(f,args...)(s) resolves to
+ * f(restitute<Ts...>(info,begin),restitute<Ts...>(info,end),args...) where
+ * info=s.type_info(), begin=s.begin(), end=s.end().
+ */
+
+template<typename F,typename... Ts>
+struct restitute_range_class;
+
+template<typename F,typename T,typename... Ts>
+struct restitute_range_class<F,T,Ts...>:
+ restitute_range_class<F,Ts...>
+{
+ using super=restitute_range_class<F,Ts...>;
+ using super::super;
+
+ template<typename SegmentInfo>
+ auto operator()(SegmentInfo&& s)
+ ->decltype(std::declval<F>()(s.begin(),s.end()))
+ {
+ using traits=iterator_traits<decltype(s.begin())>;
+ using local_iterator=typename traits::template local_iterator<T>;
+
+ if(s.type_info()==typeid(T))
+ return (this->f)(
+ local_iterator{s.begin()},local_iterator{s.end()});
+ else
+ return super::operator()(std::forward<SegmentInfo>(s));
+ }
+};
+
+template<typename F>
+struct restitute_range_class<F>
+{
+ restitute_range_class(const F& f):f{f}{}
+
+ template<typename SegmentInfo>
+ auto operator()(SegmentInfo&& s)
+ ->decltype(std::declval<F>()(s.begin(),s.end()))
+ {
+ return f(s.begin(),s.end());
+ }
+
+ F f;
+};
+
+template<typename... Ts,typename F,typename... Args>
+auto restitute_range(const F& f,Args&&... args)
+ ->restitute_range_class<
+ decltype(tail_closure(f,std::forward<Args>(args)...)),
+ Ts...
+ >
+{
+ return tail_closure(f,std::forward<Args>(args)...);
+}
+
+/* restitute_iterator<Ts...>(f,args2...)(index,it,args1...) resolves to
+ * f(restitute<Ts...>(index,it),args1...,args2...).
+ */
+
+template<typename F,typename... Ts>
+struct restitute_iterator_class;
+
+template<typename F,typename T,typename... Ts>
+struct restitute_iterator_class<F,T,Ts...>:
+ restitute_iterator_class<F,Ts...>
+{
+ using super=restitute_iterator_class<F,Ts...>;
+ using super::super;
+
+ template<typename Iterator,typename... Args>
+ auto operator()(
+ const std::type_info& info,Iterator&& it,Args&&... args)
+ ->decltype(
+ std::declval<F>()
+ (std::forward<Iterator>(it),std::forward<Args>(args)...))
+ {
+ using traits=iterator_traits<typename std::decay<Iterator>::type>;
+ using local_iterator=typename traits::template local_iterator<T>;
+
+ if(info==typeid(T))
+ return (this->f)(
+ local_iterator{it},std::forward<Args>(args)...);
+ else
+ return super::operator()(
+ info,std::forward<Iterator>(it),std::forward<Args>(args)...);
+ }
+};
+
+template<typename F>
+struct restitute_iterator_class<F>
+{
+ restitute_iterator_class(const F& f):f{f}{}
+
+ template<typename Iterator,typename... Args>
+ auto operator()(
+ const std::type_info&,Iterator&& it,Args&&... args)
+ ->decltype(
+ std::declval<F>()
+ (std::forward<Iterator>(it),std::forward<Args>(args)...))
+ {
+ return f(std::forward<Iterator>(it),std::forward<Args>(args)...);
+ }
+
+ F f;
+};
+
+template<typename... Ts,typename F,typename... Args>
+auto restitute_iterator(const F& f,Args&&... args)
+ ->restitute_iterator_class<
+ decltype(tail_closure(f,std::forward<Args>(args)...)),
+ Ts...
+ >
+{
+ return tail_closure(f,std::forward<Args>(args)...);
+}
+
+/* binary_restitute_iterator<Ts...>(f,args...)(index1,it1,index2,it2) resolves
+ * to f(restitute<Ts...>(index1,it1),restitute<Ts...>(index2,it2),args...).
+ */
+
+template<typename F,typename... Ts>
+struct binary_restitute_iterator_class
+{
+ binary_restitute_iterator_class(const F& f):f{f}{}
+
+ template<typename Iterator1,typename Iterator2>
+ auto operator()(
+ const std::type_info& info1,Iterator1&& it1,
+ const std::type_info& info2,Iterator2&& it2)
+ ->decltype(
+ std::declval<F>()
+ (std::forward<Iterator1>(it1),std::forward<Iterator2>(it2)))
+ {
+ return restitute_iterator<Ts...>(*this)(
+ info2,std::forward<Iterator2>(it2),info1,std::forward<Iterator1>(it1));
+ }
+
+ template<typename Iterator2,typename Iterator1>
+ auto operator()(
+ Iterator2&& it2,const std::type_info& info1,Iterator1&& it1)
+ ->decltype(
+ std::declval<F>()
+ (std::forward<Iterator1>(it1),std::forward<Iterator2>(it2)))
+ {
+ return restitute_iterator<Ts...>(f)(
+ info1,std::forward<Iterator1>(it1),std::forward<Iterator2>(it2));
+ }
+
+ F f;
+};
+
+template<typename... Ts,typename F,typename... Args>
+auto binary_restitute_iterator(const F& f,Args&&... args)
+ ->binary_restitute_iterator_class<
+ decltype(tail_closure(f,std::forward<Args>(args)...)),
+ Ts...
+ >
+{
+ return tail_closure(f,std::forward<Args>(args)...);
+}
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/detail/value_holder.hpp b/boost/poly_collection/detail/value_holder.hpp
new file mode 100644
index 0000000000..bd2f25c6f8
--- /dev/null
+++ b/boost/poly_collection/detail/value_holder.hpp
@@ -0,0 +1,313 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_DETAIL_VALUE_HOLDER_HPP
+#define BOOST_POLY_COLLECTION_DETAIL_VALUE_HOLDER_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/core/addressof.hpp>
+#include <boost/poly_collection/detail/is_constructible.hpp>
+#include <boost/poly_collection/detail/is_equality_comparable.hpp>
+#include <boost/poly_collection/detail/is_nothrow_eq_comparable.hpp>
+#include <boost/poly_collection/exception.hpp>
+#include <new>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* Segments of a poly_collection maintain vectors of value_holder<T>
+ * rather than directly T. This serves several purposes:
+ * - value_holder<T> is copy constructible and equality comparable even if T
+ * is not: executing the corresponding op results in a reporting exception
+ * being thrown. This allows the segment to offer its full virtual
+ * interface regardless of the properties of the concrete class contained.
+ * - value_holder<T> emulates move assignment when T is not move assignable
+ * (nothrow move constructibility required); this happens most notably with
+ * lambda functions, whose assignment operator is deleted by standard
+ * mandate [expr.prim.lambda]/20 even if the compiler generated one would
+ * work (capture by value).
+ * - To comply with [container.requirements.general]/3 (or, more precisely,
+ * its natural extension to polymorphic containers), value_holder ctors
+ * accept a first allocator arg passed by value_holder_allocator_adaptor,
+ * which must therefore be used in the vectors of value_holder's.
+ *
+ * A pointer to value_holder_base<T> can be reinterpret_cast'ed to T*.
+ * Emplacing is explicitly signalled with value_holder_emplacing_ctor to
+ * protect us from greedy T's constructible from anything (like
+ * boost::type_erasure::any).
+ */
+
+struct value_holder_emplacing_ctor_t{};
+constexpr value_holder_emplacing_ctor_t value_holder_emplacing_ctor=
+ value_holder_emplacing_ctor_t();
+
+template<typename T>
+class value_holder_base
+{
+protected:
+ typename std::aligned_storage<sizeof(T),alignof(T)>::type s;
+};
+
+template<typename T>
+class value_holder:public value_holder_base<T>
+{
+ template<typename U>
+ using enable_if_not_emplacing_ctor_t=typename std::enable_if<
+ !std::is_same<
+ typename std::decay<U>::type,value_holder_emplacing_ctor_t
+ >::value
+ >::type*;
+
+ using is_nothrow_move_constructible=std::is_nothrow_move_constructible<T>;
+ using is_copy_constructible=std::is_copy_constructible<T>;
+ using is_nothrow_copy_constructible=std::is_nothrow_copy_constructible<T>;
+ using is_move_assignable=std::is_move_assignable<T>;
+ using is_nothrow_move_assignable=std::is_nothrow_move_assignable<T>;
+ using is_equality_comparable=detail::is_equality_comparable<T>;
+ using is_nothrow_equality_comparable=
+ detail::is_nothrow_equality_comparable<T>;
+
+ T* data()noexcept{return reinterpret_cast<T*>(&this->s);}
+ const T* data()const noexcept
+ {return reinterpret_cast<const T*>(&this->s);}
+
+ T& value()noexcept{return *static_cast<T*>(data());}
+ const T& value()const noexcept{return *static_cast<const T*>(data());}
+
+public:
+ template<
+ typename Allocator,
+ enable_if_not_emplacing_ctor_t<Allocator> =nullptr
+ >
+ value_holder(Allocator& al,const T& x)
+ noexcept(is_nothrow_copy_constructible::value)
+ {copy(al,x);}
+ template<
+ typename Allocator,
+ enable_if_not_emplacing_ctor_t<Allocator> =nullptr
+ >
+ value_holder(Allocator& al,T&& x)
+ noexcept(is_nothrow_move_constructible::value)
+ {std::allocator_traits<Allocator>::construct(al,data(),std::move(x));}
+ template<
+ typename Allocator,typename... Args,
+ enable_if_not_emplacing_ctor_t<Allocator> =nullptr
+ >
+ value_holder(Allocator& al,value_holder_emplacing_ctor_t,Args&&... args)
+ {std::allocator_traits<Allocator>::construct(
+ al,data(),std::forward<Args>(args)...);}
+ template<
+ typename Allocator,
+ enable_if_not_emplacing_ctor_t<Allocator> =nullptr
+ >
+ value_holder(Allocator& al,const value_holder& x)
+ noexcept(is_nothrow_copy_constructible::value)
+ {copy(al,x.value());}
+ template<
+ typename Allocator,
+ enable_if_not_emplacing_ctor_t<Allocator> =nullptr
+ >
+ value_holder(Allocator& al,value_holder&& x)
+ noexcept(is_nothrow_move_constructible::value)
+ {std::allocator_traits<Allocator>::construct(
+ al,data(),std::move(x.value()));}
+
+ /* stdlib implementations in current use are notoriously lacking at
+ * complying with [container.requirements.general]/3, so we keep the
+ * following to make their life easier.
+ */
+
+ value_holder(const T& x)
+ noexcept(is_nothrow_copy_constructible::value)
+ {copy(x);}
+ value_holder(T&& x)
+ noexcept(is_nothrow_move_constructible::value)
+ {::new ((void*)data()) T(std::move(x));}
+ template<typename... Args>
+ value_holder(value_holder_emplacing_ctor_t,Args&&... args)
+ {::new ((void*)data()) T(std::forward<Args>(args)...);}
+ value_holder(const value_holder& x)
+ noexcept(is_nothrow_copy_constructible::value)
+ {copy(x.value());}
+ value_holder(value_holder&& x)
+ noexcept(is_nothrow_move_constructible::value)
+ {::new ((void*)data()) T(std::move(x.value()));}
+
+ value_holder& operator=(const value_holder& x)=delete;
+ value_holder& operator=(value_holder&& x)
+ noexcept(is_nothrow_move_assignable::value||!is_move_assignable::value)
+ /* if 2nd clause: nothrow move constructibility required */
+ {
+ move_assign(std::move(x.value()));
+ return *this;
+ }
+
+ ~value_holder()noexcept{value().~T();}
+
+ friend bool operator==(const value_holder& x,const value_holder& y)
+ noexcept(is_nothrow_equality_comparable::value)
+ {
+ return x.equal(y.value());
+ }
+
+private:
+ template<typename Allocator>
+ void copy(Allocator& al,const T& x){copy(al,x,is_copy_constructible{});}
+
+ template<typename Allocator>
+ void copy(Allocator& al,const T& x,std::true_type)
+ {
+ std::allocator_traits<Allocator>::construct(al,data(),x);
+ }
+
+ template<typename Allocator>
+ void copy(Allocator&,const T&,std::false_type)
+ {
+ throw not_copy_constructible{typeid(T)};
+ }
+
+ void copy(const T& x){copy(x,is_copy_constructible{});}
+
+ void copy(const T& x,std::true_type)
+ {
+ ::new (data()) T(x);
+ }
+
+ void copy(const T&,std::false_type)
+ {
+ throw not_copy_constructible{typeid(T)};
+ }
+
+ void move_assign(T&& x){move_assign(std::move(x),is_move_assignable{});}
+
+ void move_assign(T&& x,std::true_type)
+ {
+ value()=std::move(x);
+ }
+
+ void move_assign(T&& x,std::false_type)
+ {
+ /* emulated assignment */
+
+ static_assert(is_nothrow_move_constructible::value,
+ "type should be move assignable or nothrow move constructible");
+
+ if(data()!=boost::addressof(x)){
+ value().~T();
+ ::new (data()) T(std::move(x));
+ }
+ }
+
+ bool equal(const T& x)const{return equal(x,is_equality_comparable{});}
+
+ bool equal(const T& x,std::true_type)const
+ {
+ return value()==x;
+ }
+
+ bool equal(const T&,std::false_type)const
+ {
+ throw not_equality_comparable{typeid(T)};
+ }
+};
+
+template<typename Allocator>
+struct value_holder_allocator_adaptor:Allocator
+{
+ using traits=std::allocator_traits<Allocator>;
+
+ using value_type=typename traits::value_type;
+ using size_type=typename traits::size_type;
+ using difference_type=typename traits::difference_type;
+ using pointer=typename traits::pointer;
+ using const_pointer=typename traits::const_pointer;
+ using void_pointer=typename traits::void_pointer;
+ using const_void_pointer=typename traits::const_void_pointer;
+ using propagate_on_container_copy_assignment=
+ typename traits::propagate_on_container_copy_assignment;
+ using propagate_on_container_move_assignment=
+ typename traits::propagate_on_container_move_assignment;
+ using propagate_on_container_swap=
+ typename traits::propagate_on_container_swap;
+
+ template<typename U>
+ struct rebind
+ {
+ using other=value_holder_allocator_adaptor<
+ typename traits::template rebind_alloc<U>>;
+ };
+
+ value_holder_allocator_adaptor()=default;
+ value_holder_allocator_adaptor(
+ const value_holder_allocator_adaptor&)=default;
+
+ template<
+ typename Allocator2,
+ typename std::enable_if<
+ is_constructible<Allocator,Allocator2>::value
+ >::type* =nullptr
+ >
+ value_holder_allocator_adaptor(const Allocator2& x)noexcept:Allocator{x}{}
+
+ template<
+ typename Allocator2,
+ typename std::enable_if<
+ is_constructible<Allocator,Allocator2>::value
+ >::type* =nullptr
+ >
+ value_holder_allocator_adaptor(
+ const value_holder_allocator_adaptor<Allocator2>& x)noexcept:
+ Allocator{static_cast<const Allocator2&>(x)}{}
+
+ value_holder_allocator_adaptor& operator=(
+ const value_holder_allocator_adaptor&)=default;
+
+ template<typename T,typename... Args>
+ void construct(T* p,Args&&... args)
+ {
+ ::new ((void*)p) T(std::forward<Args>(args)...);
+ }
+
+ template<typename T,typename... Args>
+ void construct(value_holder<T>* p,Args&&... args)
+ {
+ ::new ((void*)p) value_holder<T>(
+ static_cast<Allocator&>(*this),std::forward<Args>(args)...);
+ }
+
+ template<typename T>
+ void destroy(T* p)
+ {
+ p->~T();
+ }
+
+ template<typename T>
+ void destroy(value_holder<T>* p)
+ {
+ traits::destroy(
+ static_cast<Allocator&>(*this),
+ reinterpret_cast<T*>(static_cast<value_holder_base<T>*>(p)));
+ }
+};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/exception.hpp b/boost/poly_collection/exception.hpp
new file mode 100644
index 0000000000..ca2c4da0bb
--- /dev/null
+++ b/boost/poly_collection/exception.hpp
@@ -0,0 +1,57 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_EXCEPTION_HPP
+#define BOOST_POLY_COLLECTION_EXCEPTION_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <stdexcept>
+#include <typeinfo>
+
+namespace boost{
+
+namespace poly_collection{
+
+struct unregistered_type:std::logic_error
+{
+ unregistered_type(const std::type_info& info):
+ std::logic_error{"type not registered"},
+ pinfo{&info}
+ {}
+
+ const std::type_info* pinfo;
+};
+
+struct not_copy_constructible:std::logic_error
+{
+ not_copy_constructible(const std::type_info& info):
+ std::logic_error{"type is not copy constructible"},
+ pinfo{&info}
+ {}
+
+ const std::type_info* pinfo;
+};
+
+struct not_equality_comparable:std::logic_error
+{
+ not_equality_comparable(const std::type_info& info):
+ std::logic_error{"type does not support equality comparison"},
+ pinfo{&info}
+ {}
+
+ const std::type_info* pinfo;
+};
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/function_collection.hpp b/boost/poly_collection/function_collection.hpp
new file mode 100644
index 0000000000..b828197a9b
--- /dev/null
+++ b/boost/poly_collection/function_collection.hpp
@@ -0,0 +1,80 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_FUNCTION_COLLECTION_HPP
+#define BOOST_POLY_COLLECTION_FUNCTION_COLLECTION_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/poly_collection/function_collection_fwd.hpp>
+#include <boost/poly_collection/detail/function_model.hpp>
+#include <boost/poly_collection/detail/poly_collection.hpp>
+#include <utility>
+
+namespace boost{
+
+namespace poly_collection{
+
+template<typename Signature,typename Allocator>
+class function_collection:
+ public detail::poly_collection_impl::poly_collection<
+ detail::function_model<Signature>,Allocator>
+{
+ using base_type=detail::poly_collection_impl::poly_collection<
+ detail::function_model<Signature>,Allocator>;
+
+ base_type& base()noexcept{return *this;}
+ const base_type& base()const noexcept{return *this;}
+
+public:
+ using base_type::base_type;
+
+ function_collection()=default;
+ function_collection(const function_collection& x)=default;
+ function_collection(function_collection&& x)=default;
+ function_collection& operator=(const function_collection& x)=default;
+ function_collection& operator=(function_collection&& x)=default;
+
+ template<typename S,typename A>
+ friend bool operator==(
+ const function_collection<S,A>&,const function_collection<S,A>&);
+};
+
+template<typename Signature,typename Allocator>
+bool operator==(
+ const function_collection<Signature,Allocator>& x,
+ const function_collection<Signature,Allocator>& y)
+{
+ return x.base()==y.base();
+}
+
+template<typename Signature,typename Allocator>
+bool operator!=(
+ const function_collection<Signature,Allocator>& x,
+ const function_collection<Signature,Allocator>& y)
+{
+ return !(x==y);
+}
+
+template<typename Signature,typename Allocator>
+void swap(
+ function_collection<Signature,Allocator>& x,
+ function_collection<Signature,Allocator>& y)
+{
+ x.swap(y);
+}
+
+} /* namespace */
+
+using poly_collection::function_collection;
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/poly_collection/function_collection_fwd.hpp b/boost/poly_collection/function_collection_fwd.hpp
new file mode 100644
index 0000000000..9ea0a0f5ff
--- /dev/null
+++ b/boost/poly_collection/function_collection_fwd.hpp
@@ -0,0 +1,57 @@
+/* Copyright 2016 Joaquin M Lopez Munoz.
+ * Distributed under the 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/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_FUNCTION_COLLECTION_FWD_HPP
+#define BOOST_POLY_COLLECTION_FUNCTION_COLLECTION_FWD_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <memory>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+template<typename Signature> struct function_model;
+}
+
+template<typename Signature>
+using function_collection_value_type=
+ typename detail::function_model<Signature>::value_type;
+
+template<
+ typename Signature,
+ typename Allocator=std::allocator<function_collection_value_type<Signature>>
+>
+class function_collection;
+
+template<typename Signature,typename Allocator>
+bool operator==(
+ const function_collection<Signature,Allocator>& x,
+ const function_collection<Signature,Allocator>& y);
+
+template<typename Signature,typename Allocator>
+bool operator!=(
+ const function_collection<Signature,Allocator>& x,
+ const function_collection<Signature,Allocator>& y);
+
+template<typename Signature,typename Allocator>
+void swap(
+ function_collection<Signature,Allocator>& x,
+ function_collection<Signature,Allocator>& y);
+
+} /* namespace poly_collection */
+
+using poly_collection::function_collection;
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/predef/architecture/arm.h b/boost/predef/architecture/arm.h
index b200c62777..76f9f947bd 100644
--- a/boost/predef/architecture/arm.h
+++ b/boost/predef/architecture/arm.h
@@ -27,11 +27,13 @@ http://www.boost.org/LICENSE_1_0.txt)
[[`__TARGET_ARCH_ARM`] [__predef_detection__]]
[[`__TARGET_ARCH_THUMB`] [__predef_detection__]]
[[`_M_ARM`] [__predef_detection__]]
+ [[`_M_ARM64`] [__predef_detection__]]
[[`__arm64`] [8.0.0]]
[[`__TARGET_ARCH_ARM`] [V.0.0]]
[[`__TARGET_ARCH_THUMB`] [V.0.0]]
[[`_M_ARM`] [V.0.0]]
+ [[`_M_ARM64`] [8.0.0]]
]
*/
@@ -39,7 +41,7 @@ http://www.boost.org/LICENSE_1_0.txt)
#if defined(__arm__) || defined(__arm64) || defined(__thumb__) || \
defined(__TARGET_ARCH_ARM) || defined(__TARGET_ARCH_THUMB) || \
- defined(_M_ARM)
+ defined(_M_ARM) || defined(_M_ARM64)
# undef BOOST_ARCH_ARM
# if !defined(BOOST_ARCH_ARM) && defined(__arm64)
# define BOOST_ARCH_ARM BOOST_VERSION_NUMBER(8,0,0)
@@ -50,6 +52,9 @@ http://www.boost.org/LICENSE_1_0.txt)
# 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_ARM64)
+# define BOOST_ARCH_ARM BOOST_VERSION_NUMBER(8,0,0)
+# endif
# if !defined(BOOST_ARCH_ARM) && defined(_M_ARM)
# define BOOST_ARCH_ARM BOOST_VERSION_NUMBER(_M_ARM,0,0)
# endif
diff --git a/boost/predef/compiler/intel.h b/boost/predef/compiler/intel.h
index 3bd76fee08..f8a17ef437 100644
--- a/boost/predef/compiler/intel.h
+++ b/boost/predef/compiler/intel.h
@@ -1,5 +1,5 @@
/*
-Copyright Rene Rivera 2008-2015
+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)
@@ -34,6 +34,13 @@ Version number available as major, minor, and patch.
#if defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || \
defined(__ECC)
+/*`
+[note Because of an Intel mistake in the release version numbering when
+`__INTEL_COMPILER` is `9999` it is detected as version 12.1.0.]
+ */
+# 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)), \
diff --git a/boost/predef/hardware/simd/arm.h b/boost/predef/hardware/simd/arm.h
index d067c93196..3b3fc3fa36 100644
--- a/boost/predef/hardware/simd/arm.h
+++ b/boost/predef/hardware/simd/arm.h
@@ -24,6 +24,7 @@ http://www.boost.org/LICENSE_1_0.txt)
[[`__ARM_NEON__`] [__predef_detection__]]
[[`__aarch64__`] [__predef_detection__]]
[[`_M_ARM`] [__predef_detection__]]
+ [[`_M_ARM64`] [__predef_detection__]]
]
[table
@@ -32,6 +33,7 @@ http://www.boost.org/LICENSE_1_0.txt)
[[`__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]]
]
*/
@@ -39,7 +41,7 @@ http://www.boost.org/LICENSE_1_0.txt)
#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))
+#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
diff --git a/boost/predef/other/workaround.h b/boost/predef/other/workaround.h
new file mode 100644
index 0000000000..7167a18ac6
--- /dev/null
+++ b/boost/predef/other/workaround.h
@@ -0,0 +1,87 @@
+/*
+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
+
+/*`
+[heading `BOOST_PREDEF_WORKAROUND`]
+
+``
+BOOST_PREDEF_WORKAROUND(symbol,comp,major,minor,patch)
+``
+
+Usage:
+
+``
+#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)`.
+*/
+#ifdef BOOST_STRICT_CONFIG
+# define BOOST_PREDEF_WORKAROUND(symbol, comp, major, minor, patch) (0)
+#else
+# include <boost/predef/version_number.h>
+# define BOOST_PREDEF_WORKAROUND(symbol, comp, major, minor, patch) \
+ ( (symbol) != (0) ) && \
+ ( (symbol) comp (BOOST_VERSION_NUMBER( (major) , (minor) , (patch) )) )
+#endif
+
+/*`
+[heading `BOOST_PREDEF_TESTED_AT`]
+
+``
+BOOST_PREDEF_TESTED_AT(symbol,major,minor,patch)
+``
+
+Usage:
+
+``
+#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.
+*/
+#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/platform.h b/boost/predef/platform.h
index c0c8706e8a..7da697e63d 100644
--- a/boost/predef/platform.h
+++ b/boost/predef/platform.h
@@ -16,6 +16,7 @@ http://www.boost.org/LICENSE_1_0.txt)
#include <boost/predef/platform/windows_store.h>
#include <boost/predef/platform/windows_phone.h>
#include <boost/predef/platform/windows_runtime.h>
+#include <boost/predef/platform/ios.h>
/*#include <boost/predef/platform/.h>*/
#endif
diff --git a/boost/predef/platform/ios.h b/boost/predef/platform/ios.h
new file mode 100644
index 0000000000..af1c364cf0
--- /dev/null
+++ b/boost/predef/platform/ios.h
@@ -0,0 +1,58 @@
+/*
+Copyright Ruslan Baratov 2017
+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_PLAT_IOS_H
+#define BOOST_PREDEF_PLAT_IOS_H
+
+#include <boost/predef/os/ios.h> // BOOST_OS_IOS
+#include <boost/predef/version_number.h> // BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+/*`
+[heading `BOOST_PLAT_IOS_DEVICE`]
+[heading `BOOST_PLAT_IOS_SIMULATOR`]
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`TARGET_IPHONE_SIMULATOR`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_PLAT_IOS_DEVICE BOOST_VERSION_NUMBER_NOT_AVAILABLE
+#define BOOST_PLAT_IOS_SIMULATOR BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h
+#if BOOST_OS_IOS
+# include <TargetConditionals.h>
+# if TARGET_IPHONE_SIMULATOR == 1
+# undef BOOST_PLAT_IOS_SIMULATOR
+# define BOOST_PLAT_IOS_SIMULATOR BOOST_VERSION_NUMBER_AVAILABLE
+# else
+# undef BOOST_PLAT_IOS_DEVICE
+# define BOOST_PLAT_IOS_DEVICE BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_PLAT_IOS_SIMULATOR
+# define BOOST_PLAT_IOS_SIMULATOR_AVAILABLE
+# include <boost/predef/detail/platform_detected.h>
+#endif
+
+#if BOOST_PLAT_IOS_DEVICE
+# define BOOST_PLAT_IOS_DEVICE_AVAILABLE
+# include <boost/predef/detail/platform_detected.h>
+#endif
+
+#define BOOST_PLAT_IOS_SIMULATOR_NAME "iOS Simulator"
+#define BOOST_PLAT_IOS_DEVICE_NAME "iOS Device"
+
+#endif // BOOST_PREDEF_PLAT_IOS_H
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_PLAT_IOS_SIMULATOR,BOOST_PLAT_IOS_SIMULATOR_NAME)
+BOOST_PREDEF_DECLARE_TEST(BOOST_PLAT_IOS_DEVICE,BOOST_PLAT_IOS_DEVICE_NAME)
diff --git a/boost/predef/platform/mingw.h b/boost/predef/platform/mingw.h
index 64c5837364..5a1334b47c 100644
--- a/boost/predef/platform/mingw.h
+++ b/boost/predef/platform/mingw.h
@@ -5,8 +5,8 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef BOOST_PREDEF_COMPILER_MINGW_H
-#define BOOST_PREDEF_COMPILER_MINGW_H
+#ifndef BOOST_PREDEF_PLAT_MINGW_H
+#define BOOST_PREDEF_PLAT_MINGW_H
#include <boost/predef/version_number.h>
#include <boost/predef/make.h>
diff --git a/boost/predef/version.h b/boost/predef/version.h
index ebd2b4fd9f..e03469f68d 100644
--- a/boost/predef/version.h
+++ b/boost/predef/version.h
@@ -10,6 +10,6 @@ http://www.boost.org/LICENSE_1_0.txt)
#include <boost/predef/version_number.h>
-#define BOOST_PREDEF_VERSION BOOST_VERSION_NUMBER(1,5,0)
+#define BOOST_PREDEF_VERSION BOOST_VERSION_NUMBER(1,6,0)
#endif
diff --git a/boost/preprocessor/config/config.hpp b/boost/preprocessor/config/config.hpp
index 4801903141..28dcdd4642 100644
--- a/boost/preprocessor/config/config.hpp
+++ b/boost/preprocessor/config/config.hpp
@@ -25,18 +25,16 @@
# define BOOST_PP_CONFIG_DMC() 0x0040
#
# ifndef BOOST_PP_CONFIG_FLAGS
-# if defined(__GCCXML__)
-# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_STRICT())
-# elif defined(__WAVE__)
-# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_STRICT())
-# elif defined(__MWERKS__) && __MWERKS__ >= 0x3200
+# if defined(__GCCXML__) || defined(__WAVE__) || defined(__MWERKS__) && __MWERKS__ >= 0x3200
# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_STRICT())
# elif defined(__EDG__) || defined(__EDG_VERSION__)
-# if defined(_MSC_VER) && (defined(__clang__) || defined(__INTELLISENSE__) || __EDG_VERSION__ >= 308)
+# if defined(_MSC_VER) && !defined(__clang__) && (defined(__INTELLISENSE__) || __EDG_VERSION__ >= 308)
# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_MSVC())
# else
# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_EDG() | BOOST_PP_CONFIG_STRICT())
# endif
+# elif defined(_MSC_VER) && defined(__clang__)
+# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_STRICT())
# elif defined(__MWERKS__)
# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_MWCC())
# elif defined(__DMC__)
@@ -75,8 +73,10 @@
# /* variadic support explicitly disabled for all untested compilers */
# if defined __GCCXML__ || defined __CUDACC__ || defined __PATHSCALE__ || defined __DMC__ || defined __CODEGEARC__ || defined __BORLANDC__ || defined __MWERKS__ || ( defined __SUNPRO_CC && __SUNPRO_CC < 0x5120 ) || defined __HP_aCC && !defined __EDG__ || defined __MRC__ || defined __SC__ || defined __IBMCPP__ || defined __PGI
# define BOOST_PP_VARIADICS 0
+# elif defined(_MSC_VER) && defined(__clang__)
+# define BOOST_PP_VARIADICS 1
# /* VC++ (C/C++) and Intel C++ Compiler >= 17.0 with MSVC */
-# elif defined _MSC_VER && _MSC_VER >= 1400 && (defined(__clang__) || !defined __EDG__ || defined(__INTELLISENSE__) || defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1700)
+# elif defined _MSC_VER && _MSC_VER >= 1400 && (!defined __EDG__ || defined(__INTELLISENSE__) || defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1700)
# define BOOST_PP_VARIADICS 1
# undef BOOST_PP_VARIADICS_MSVC
# define BOOST_PP_VARIADICS_MSVC 1
@@ -92,7 +92,7 @@
# elif !BOOST_PP_VARIADICS + 1 < 2
# undef BOOST_PP_VARIADICS
# define BOOST_PP_VARIADICS 1
-# if defined _MSC_VER && _MSC_VER >= 1400 && (defined(__clang__) || defined(__INTELLISENSE__) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1700) || !(defined __EDG__ || defined __GCCXML__ || defined __CUDACC__ || defined __PATHSCALE__ || defined __DMC__ || defined __CODEGEARC__ || defined __BORLANDC__ || defined __MWERKS__ || defined __SUNPRO_CC || defined __HP_aCC || defined __MRC__ || defined __SC__ || defined __IBMCPP__ || defined __PGI))
+# if defined _MSC_VER && _MSC_VER >= 1400 && !defined(__clang__) && (defined(__INTELLISENSE__) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1700) || !(defined __EDG__ || defined __GCCXML__ || defined __CUDACC__ || defined __PATHSCALE__ || defined __DMC__ || defined __CODEGEARC__ || defined __BORLANDC__ || defined __MWERKS__ || defined __SUNPRO_CC || defined __HP_aCC || defined __MRC__ || defined __SC__ || defined __IBMCPP__ || defined __PGI))
# undef BOOST_PP_VARIADICS_MSVC
# define BOOST_PP_VARIADICS_MSVC 1
# endif
diff --git a/boost/program_options/detail/value_semantic.hpp b/boost/program_options/detail/value_semantic.hpp
index 978a38a86e..9531339a34 100644
--- a/boost/program_options/detail/value_semantic.hpp
+++ b/boost/program_options/detail/value_semantic.hpp
@@ -8,6 +8,9 @@
#include <boost/throw_exception.hpp>
+// forward declaration
+namespace boost { template<class T> class optional; }
+
namespace boost { namespace program_options {
extern BOOST_PROGRAM_OPTIONS_DECL std::string arg;
@@ -152,6 +155,20 @@ namespace boost { namespace program_options {
}
}
+ /** Validates optional arguments. */
+ template<class T, class charT>
+ void validate(boost::any& v,
+ const std::vector<std::basic_string<charT> >& s,
+ boost::optional<T>*,
+ int)
+ {
+ validators::check_first_occurrence(v);
+ validators::get_single_string(s);
+ boost::any a;
+ validate(a, s, (T*)0, 0);
+ v = boost::any(boost::optional<T>(boost::any_cast<T>(a)));
+ }
+
template<class T, class charT>
void
typed_value<T, charT>::
diff --git a/boost/program_options/eof_iterator.hpp b/boost/program_options/eof_iterator.hpp
index 4eeef0e937..5e53df5b81 100644
--- a/boost/program_options/eof_iterator.hpp
+++ b/boost/program_options/eof_iterator.hpp
@@ -68,7 +68,11 @@ namespace boost {
private: // iterator core operations
- friend class iterator_core_access;
+#ifdef __DCC__
+ friend class boost::iterator_core_access;
+#else
+ friend class iterator_core_access;
+#endif
void increment()
{
diff --git a/boost/program_options/errors.hpp b/boost/program_options/errors.hpp
index f31defbd36..ba83d88f40 100644
--- a/boost/program_options/errors.hpp
+++ b/boost/program_options/errors.hpp
@@ -26,7 +26,12 @@ namespace boost { namespace program_options {
inline std::string strip_prefixes(const std::string& text)
{
// "--foo-bar" -> "foo-bar"
- return text.substr(text.find_first_not_of("-/"));
+ std::string::size_type i = text.find_first_not_of("-/");
+ if (i == std::string::npos) {
+ return text;
+ } else {
+ return text.substr(i);
+ }
}
/** Base class for all errors in the library. */
@@ -169,7 +174,7 @@ namespace boost { namespace program_options {
virtual void set_option_name(const std::string& option_name)
{ set_substitute("option", option_name);}
- std::string get_option_name() const throw()
+ std::string get_option_name() const
{ return get_canonical_option_name(); }
void set_original_token(const std::string& original_token)
diff --git a/boost/program_options/option.hpp b/boost/program_options/option.hpp
index 1fa6a19234..427678fa78 100644
--- a/boost/program_options/option.hpp
+++ b/boost/program_options/option.hpp
@@ -31,6 +31,7 @@ namespace boost { namespace program_options {
basic_option(const std::string& xstring_key,
const std::vector< std::string> &xvalue)
: string_key(xstring_key)
+ , position_key(-1)
, value(xvalue)
, unregistered(false)
, case_insensitive(false)
diff --git a/boost/program_options/value_semantic.hpp b/boost/program_options/value_semantic.hpp
index be3f10801e..ac9dbc663b 100644
--- a/boost/program_options/value_semantic.hpp
+++ b/boost/program_options/value_semantic.hpp
@@ -38,11 +38,6 @@ namespace boost { namespace program_options {
should be present on the command line. */
virtual unsigned max_tokens() const = 0;
- /** Returns true if the option should only take adjacent token,
- not one from further command-line arguments.
- */
- virtual bool adjacent_tokens_only() const = 0;
-
/** Returns true if values from different sources should be composed.
Otherwise, value from the first source is used and values from
other sources are discarded.
@@ -53,7 +48,7 @@ namespace boost { namespace program_options {
*/
virtual bool is_required() const = 0;
-
+
/** Parses a group of tokens that specify a value of option.
Stores the result in 'value_store', using whatever representation
is desired. May be be called several times if value of the same
@@ -139,7 +134,6 @@ namespace boost { namespace program_options {
unsigned min_tokens() const;
unsigned max_tokens() const;
- bool adjacent_tokens_only() const { return false; }
bool is_composing() const { return false; }
@@ -224,10 +218,7 @@ namespace boost { namespace program_options {
/** Specifies an implicit value, which will be used
if the option is given, but without an adjacent value.
- Using this implies that an explicit value is optional, but if
- given, must be strictly adjacent to the option, i.e.: '-ovalue'
- or '--option=value'. Giving '-o' or '--option' will cause the
- implicit value to be applied.
+ Using this implies that an explicit value is optional,
*/
typed_value* implicit_value(const T &v)
{
@@ -331,8 +322,6 @@ namespace boost { namespace program_options {
}
}
- bool adjacent_tokens_only() const { return !m_implicit_value.empty(); }
-
bool is_required() const { return m_required; }
/** Creates an instance of the 'validator' class and calls
diff --git a/boost/program_options/version.hpp b/boost/program_options/version.hpp
index 748094361b..aa27568bb8 100644
--- a/boost/program_options/version.hpp
+++ b/boost/program_options/version.hpp
@@ -15,5 +15,8 @@
#endif
#define BOOST_PROGRAM_OPTIONS_VERSION 2
+// Signal that implicit options will use values from next
+// token, if available.
+#define BOOST_PROGRAM_OPTIONS_IMPLICIT_VALUE_NEXT_TOKEN 1
#endif
diff --git a/boost/python.hpp b/boost/python.hpp
index 11067c1702..e484034103 100644
--- a/boost/python.hpp
+++ b/boost/python.hpp
@@ -42,7 +42,6 @@
# include <boost/python/make_function.hpp>
# include <boost/python/manage_new_object.hpp>
# include <boost/python/module.hpp>
-# include <boost/python/numeric.hpp>
# include <boost/python/object.hpp>
# include <boost/python/object_protocol.hpp>
# include <boost/python/object_protocol_core.hpp>
diff --git a/boost/python/arg_from_python.hpp b/boost/python/arg_from_python.hpp
index 05611edbbd..983726b065 100755
--- a/boost/python/arg_from_python.hpp
+++ b/boost/python/arg_from_python.hpp
@@ -9,7 +9,7 @@
# include <boost/python/converter/arg_from_python.hpp>
# if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \
|| BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(800))
-# include <boost/type_traits/remove_cv.hpp>
+# include <boost/python/detail/type_traits.hpp>
#endif
namespace boost { namespace python {
@@ -19,7 +19,7 @@ struct arg_from_python
: converter::select_arg_from_python<
# if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \
|| BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(800))
- typename boost::remove_cv<T>::type
+ typename detail::remove_cv<T>::type
# else
T
# endif
@@ -28,7 +28,7 @@ struct arg_from_python
typedef typename converter::select_arg_from_python<
# if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \
|| BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(800))
- typename boost::remove_cv<T>::type
+ typename detail::remove_cv<T>::type
# else
T
# endif
diff --git a/boost/python/args.hpp b/boost/python/args.hpp
index 55d1283b5a..27731bd8c9 100644
--- a/boost/python/args.hpp
+++ b/boost/python/args.hpp
@@ -11,10 +11,7 @@
# include <boost/config.hpp>
# include <boost/python/detail/preprocessor.hpp>
# include <boost/python/detail/type_list.hpp>
-
-# include <boost/type_traits/is_reference.hpp>
-# include <boost/type_traits/remove_reference.hpp>
-# include <boost/type_traits/remove_cv.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/preprocessor/enum_params.hpp>
# include <boost/preprocessor/repeat.hpp>
@@ -116,9 +113,9 @@ namespace detail
template <class T>
struct is_reference_to_keywords
{
- BOOST_STATIC_CONSTANT(bool, is_ref = is_reference<T>::value);
- typedef typename remove_reference<T>::type deref;
- typedef typename remove_cv<deref>::type key_t;
+ BOOST_STATIC_CONSTANT(bool, is_ref = detail::is_reference<T>::value);
+ typedef typename detail::remove_reference<T>::type deref;
+ typedef typename detail::remove_cv<deref>::type key_t;
BOOST_STATIC_CONSTANT(bool, is_key = is_keywords<key_t>::value);
BOOST_STATIC_CONSTANT(bool, value = (is_ref & is_key));
diff --git a/boost/python/bases.hpp b/boost/python/bases.hpp
index 614d62232b..efcac3f389 100644
--- a/boost/python/bases.hpp
+++ b/boost/python/bases.hpp
@@ -6,8 +6,8 @@
# define BASES_DWA2002321_HPP
# include <boost/python/detail/prefix.hpp>
-# include <boost/type_traits/object_traits.hpp>
# include <boost/python/detail/type_list.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/mpl/if.hpp>
# include <boost/mpl/bool.hpp>
# include <boost/preprocessor/enum_params_with_a_default.hpp>
diff --git a/boost/python/cast.hpp b/boost/python/cast.hpp
index bad7e28240..c0dd229e84 100755
--- a/boost/python/cast.hpp
+++ b/boost/python/cast.hpp
@@ -6,9 +6,8 @@
# define CAST_DWA200269_HPP
# include <boost/python/detail/prefix.hpp>
+# include <boost/python/detail/type_traits.hpp>
-# include <boost/type_traits/same_traits.hpp>
-# include <boost/type_traits/cv_traits.hpp>
# include <boost/type.hpp>
# include <boost/python/base_type_traits.hpp>
# include <boost/python/detail/convertible.hpp>
@@ -76,9 +75,9 @@ namespace detail
template <class Source, class Target>
inline Target* upcast_impl(Source* x, Target*)
{
- typedef typename add_cv<Source>::type src_t;
- typedef typename add_cv<Target>::type target_t;
- bool const same = is_same<src_t,target_t>::value;
+ typedef typename detail::add_cv<Source>::type src_t;
+ typedef typename detail::add_cv<Target>::type target_t;
+ bool const same = detail::is_same<src_t,target_t>::value;
return detail::upcaster<same>::execute(x, (Target*)0);
}
diff --git a/boost/python/class.hpp b/boost/python/class.hpp
index 70ca6d01b3..77f915ba0a 100644
--- a/boost/python/class.hpp
+++ b/boost/python/class.hpp
@@ -28,13 +28,10 @@
# include <boost/python/detail/operator_id.hpp>
# include <boost/python/detail/def_helper.hpp>
# include <boost/python/detail/force_instantiate.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/python/detail/unwrap_type_id.hpp>
# include <boost/python/detail/unwrap_wrapper.hpp>
-# include <boost/type_traits/is_same.hpp>
-# include <boost/type_traits/is_member_function_pointer.hpp>
-# include <boost/type_traits/is_polymorphic.hpp>
-
# include <boost/mpl/size.hpp>
# include <boost/mpl/for_each.hpp>
# include <boost/mpl/bool.hpp>
@@ -53,7 +50,6 @@
# ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
# include <boost/mpl/and.hpp>
-# include <boost/type_traits/is_member_pointer.hpp>
# endif
namespace boost { namespace python {
@@ -84,8 +80,8 @@ namespace detail
template <class T>
struct is_data_member_pointer
: mpl::and_<
- is_member_pointer<T>
- , mpl::not_<is_member_function_pointer<T> >
+ detail::is_member_pointer<T>
+ , mpl::not_<detail::is_member_function_pointer<T> >
>
{};
@@ -138,11 +134,11 @@ namespace detail
must_be_derived_class_member(Default const&)
{
// https://svn.boost.org/trac/boost/ticket/5803
- //typedef typename assertion<mpl::not_<is_same<Default,Fn> > >::failed test0;
+ //typedef typename assertion<mpl::not_<detail::is_same<Default,Fn> > >::failed test0;
# if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
- typedef typename assertion<is_polymorphic<T> >::failed test1 BOOST_ATTRIBUTE_UNUSED;
+ typedef typename assertion<detail::is_polymorphic<T> >::failed test1 BOOST_ATTRIBUTE_UNUSED;
# endif
- typedef typename assertion<is_member_function_pointer<Fn> >::failed test2 BOOST_ATTRIBUTE_UNUSED;
+ typedef typename assertion<detail::is_member_function_pointer<Fn> >::failed test2 BOOST_ATTRIBUTE_UNUSED;
not_a_derived_class_member<Default>(Fn());
}
};
diff --git a/boost/python/converter/arg_from_python.hpp b/boost/python/converter/arg_from_python.hpp
index 61bbaad570..0c0daabc1f 100644
--- a/boost/python/converter/arg_from_python.hpp
+++ b/boost/python/converter/arg_from_python.hpp
@@ -8,8 +8,7 @@
# include <boost/python/detail/prefix.hpp>
# include <boost/python/converter/from_python.hpp>
# include <boost/python/detail/indirect_traits.hpp>
-# include <boost/type_traits/transform_traits.hpp>
-# include <boost/type_traits/cv_traits.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/python/converter/rvalue_from_python_data.hpp>
# include <boost/mpl/eval_if.hpp>
# include <boost/mpl/if.hpp>
@@ -106,7 +105,7 @@ struct reference_arg_from_python : arg_lvalue_from_python_base
template <class T>
struct arg_rvalue_from_python
{
- typedef typename boost::add_reference<
+ typedef typename boost::python::detail::add_lvalue_reference<
T
// We can't add_const here, or it would be impossible to pass
// auto_ptr<U> args from Python to C++
diff --git a/boost/python/converter/arg_to_python.hpp b/boost/python/converter/arg_to_python.hpp
index 3a19ec4395..bbecae72e5 100755
--- a/boost/python/converter/arg_to_python.hpp
+++ b/boost/python/converter/arg_to_python.hpp
@@ -24,11 +24,7 @@
# include <boost/python/detail/convertible.hpp>
# include <boost/python/detail/string_literal.hpp>
# include <boost/python/detail/value_is_shared_ptr.hpp>
-
-# include <boost/type_traits/cv_traits.hpp>
-# include <boost/type_traits/composite_traits.hpp>
-# include <boost/type_traits/function_traits.hpp>
-
+# include <boost/python/detail/type_traits.hpp>
# include <boost/mpl/or.hpp>
@@ -116,9 +112,9 @@ namespace detail
, typename mpl::if_<
mpl::or_<
- is_function<T>
+ boost::python::detail::is_function<T>
, indirect_traits::is_pointer_to_function<T>
- , is_member_function_pointer<T>
+ , boost::python::detail::is_member_function_pointer<T>
>
, function_arg_to_python<T>
@@ -127,7 +123,7 @@ namespace detail
, object_manager_arg_to_python<T>
, typename mpl::if_<
- is_pointer<T>
+ boost::python::detail::is_pointer<T>
, pointer_deep_arg_to_python<T>
, typename mpl::if_<
diff --git a/boost/python/converter/object_manager.hpp b/boost/python/converter/object_manager.hpp
index 4668245545..b2271a7ea2 100644
--- a/boost/python/converter/object_manager.hpp
+++ b/boost/python/converter/object_manager.hpp
@@ -8,7 +8,7 @@
# include <boost/python/handle.hpp>
# include <boost/python/cast.hpp>
# include <boost/python/converter/pyobject_traits.hpp>
-# include <boost/type_traits/object_traits.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/mpl/if.hpp>
# include <boost/python/detail/indirect_traits.hpp>
# include <boost/mpl/bool.hpp>
diff --git a/boost/python/converter/pointer_type_id.hpp b/boost/python/converter/pointer_type_id.hpp
index 963f58f717..49eeda42cb 100644
--- a/boost/python/converter/pointer_type_id.hpp
+++ b/boost/python/converter/pointer_type_id.hpp
@@ -6,7 +6,7 @@
# define POINTER_TYPE_ID_DWA2002222_HPP
# include <boost/python/type_id.hpp>
-# include <boost/type_traits/composite_traits.hpp>
+# include <boost/python/detail/type_traits.hpp>
namespace boost { namespace python { namespace converter {
@@ -59,7 +59,7 @@ template <class T>
type_info pointer_type_id(T(*)() = 0)
{
return detail::pointer_typeid_select<
- is_reference<T>::value
+ boost::python::detail::is_lvalue_reference<T>::value
>::execute((T(*)())0);
}
diff --git a/boost/python/converter/pytype_function.hpp b/boost/python/converter/pytype_function.hpp
index 95d0f66d46..8e0a4e7995 100755
--- a/boost/python/converter/pytype_function.hpp
+++ b/boost/python/converter/pytype_function.hpp
@@ -8,6 +8,7 @@
# include <boost/python/detail/prefix.hpp>
# include <boost/python/converter/registered.hpp>
# include <boost/python/detail/unwind_type.hpp>
+# include <boost/python/detail/type_traits.hpp>
namespace boost { namespace python {
@@ -53,7 +54,7 @@ inline python::type_info unwind_type_id_(boost::type<void>* = 0, mpl::true_* =0)
template <class T>
inline python::type_info unwind_type_id(boost::type<T>* p= 0)
{
- return unwind_type_id_(p, (mpl::bool_<boost::is_void<T>::value >*)0 );
+ return unwind_type_id_(p, (mpl::bool_<boost::python::detail::is_void<T>::value >*)0 );
}
}
@@ -64,7 +65,7 @@ struct expected_pytype_for_arg
static PyTypeObject const *get_pytype()
{
const converter::registration *r=converter::registry::query(
- detail::unwind_type_id_((boost::type<T>*)0, (mpl::bool_<boost::is_void<T>::value >*)0 )
+ detail::unwind_type_id_((boost::type<T>*)0, (mpl::bool_<boost::python::detail::is_void<T>::value >*)0 )
);
return r ? r->expected_from_python_type(): 0;
}
@@ -77,7 +78,7 @@ struct registered_pytype
static PyTypeObject const *get_pytype()
{
const converter::registration *r=converter::registry::query(
- detail::unwind_type_id_((boost::type<T>*) 0, (mpl::bool_<boost::is_void<T>::value >*)0 )
+ detail::unwind_type_id_((boost::type<T>*) 0, (mpl::bool_<boost::python::detail::is_void<T>::value >*)0 )
);
return r ? r->m_class_object: 0;
}
@@ -111,7 +112,7 @@ struct to_python_target_type
static PyTypeObject const *get_pytype()
{
const converter::registration *r=converter::registry::query(
- detail::unwind_type_id_((boost::type<T>*)0, (mpl::bool_<boost::is_void<T>::value >*)0 )
+ detail::unwind_type_id_((boost::type<T>*)0, (mpl::bool_<boost::python::detail::is_void<T>::value >*)0 )
);
return r ? r->to_python_target_type(): 0;
}
diff --git a/boost/python/converter/registered.hpp b/boost/python/converter/registered.hpp
index a622250dca..73f4d98466 100644
--- a/boost/python/converter/registered.hpp
+++ b/boost/python/converter/registered.hpp
@@ -10,9 +10,7 @@
#include <boost/python/type_id.hpp>
#include <boost/python/converter/registry.hpp>
#include <boost/python/converter/registrations.hpp>
-#include <boost/type_traits/transform_traits.hpp>
-#include <boost/type_traits/cv_traits.hpp>
-#include <boost/type_traits/is_void.hpp>
+#include <boost/python/detail/type_traits.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/type.hpp>
#include <memory>
@@ -44,8 +42,8 @@ namespace detail
template <class T>
struct registered
: detail::registered_base<
- typename add_reference<
- typename add_cv<T>::type
+ typename boost::python::detail::add_lvalue_reference<
+ typename boost::python::detail::add_cv<T>::type
>::type
>
{
diff --git a/boost/python/converter/registered_pointee.hpp b/boost/python/converter/registered_pointee.hpp
index 974cb6d810..28b2988c7f 100644
--- a/boost/python/converter/registered_pointee.hpp
+++ b/boost/python/converter/registered_pointee.hpp
@@ -7,8 +7,7 @@
# include <boost/python/converter/registered.hpp>
# include <boost/python/converter/pointer_type_id.hpp>
# include <boost/python/converter/registry.hpp>
-# include <boost/type_traits/transform_traits.hpp>
-# include <boost/type_traits/cv_traits.hpp>
+# include <boost/python/detail/type_traits.hpp>
namespace boost { namespace python { namespace converter {
@@ -17,9 +16,9 @@ struct registration;
template <class T>
struct registered_pointee
: registered<
- typename remove_pointer<
- typename remove_cv<
- typename remove_reference<T>::type
+ typename boost::python::detail::remove_pointer<
+ typename boost::python::detail::remove_cv<
+ typename boost::python::detail::remove_reference<T>::type
>::type
>::type
>
diff --git a/boost/python/converter/return_from_python.hpp b/boost/python/converter/return_from_python.hpp
index 5db9748545..a995a2905a 100755
--- a/boost/python/converter/return_from_python.hpp
+++ b/boost/python/converter/return_from_python.hpp
@@ -14,7 +14,7 @@
# include <boost/python/detail/void_return.hpp>
# include <boost/python/errors.hpp>
# include <boost/python/handle.hpp>
-# include <boost/type_traits/has_trivial_copy.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/mpl/and.hpp>
# include <boost/mpl/bool.hpp>
diff --git a/boost/python/converter/rvalue_from_python_data.hpp b/boost/python/converter/rvalue_from_python_data.hpp
index 471a5255b6..acb38f8498 100644
--- a/boost/python/converter/rvalue_from_python_data.hpp
+++ b/boost/python/converter/rvalue_from_python_data.hpp
@@ -8,9 +8,8 @@
# include <boost/python/converter/constructor_function.hpp>
# include <boost/python/detail/referent_storage.hpp>
# include <boost/python/detail/destroy.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/static_assert.hpp>
-# include <boost/type_traits/add_reference.hpp>
-# include <boost/type_traits/add_cv.hpp>
# include <cstddef>
// Data management for potential rvalue conversions from Python to C++
@@ -78,7 +77,7 @@ struct rvalue_from_python_storage
// Storage for the result, in case an rvalue must be constructed
typename python::detail::referent_storage<
- typename add_reference<T>::type
+ typename boost::python::detail::add_lvalue_reference<T>::type
>::type storage;
};
@@ -110,7 +109,8 @@ struct rvalue_from_python_data : rvalue_from_python_storage<T>
// Destroys any object constructed in the storage.
~rvalue_from_python_data();
private:
- typedef typename add_reference<typename add_cv<T>::type>::type ref_type;
+ typedef typename boost::python::detail::add_lvalue_reference<
+ typename boost::python::detail::add_cv<T>::type>::type ref_type;
};
//
diff --git a/boost/python/data_members.hpp b/boost/python/data_members.hpp
index 5d3309cf97..989f7d7f93 100644
--- a/boost/python/data_members.hpp
+++ b/boost/python/data_members.hpp
@@ -19,14 +19,7 @@
# include <boost/python/detail/indirect_traits.hpp>
# include <boost/python/detail/not_specified.hpp>
# include <boost/python/detail/value_arg.hpp>
-
-# include <boost/type_traits/add_const.hpp>
-# include <boost/type_traits/add_reference.hpp>
-# include <boost/type_traits/is_member_pointer.hpp>
-
-# if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
-# include <boost/type_traits/remove_cv.hpp>
-# endif
+# include <boost/python/detail/type_traits.hpp>
# include <boost/mpl/eval_if.hpp>
# include <boost/mpl/if.hpp>
@@ -147,20 +140,20 @@ namespace detail
// boost::python::make_getter are used to dispatch behavior. The
// third argument is a workaround for a CWPro8 partial ordering bug
// with pointers to data members. It should be convertible to
- // mpl::true_ iff the first argument is a pointer-to-member, and
- // mpl::false_ otherwise. The fourth argument is for compilers
+ // detail::true_ iff the first argument is a pointer-to-member, and
+ // detail::false_ otherwise. The fourth argument is for compilers
// which don't support partial ordering at all and should always be
// passed 0L.
- //
+
#if BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
template <class D, class P>
- inline object make_getter(D& d, P& p, mpl::false_, ...);
+ inline object make_getter(D& d, P& p, detail::false_, ...);
#endif
// Handle non-member pointers with policies
template <class D, class Policies>
- inline object make_getter(D* d, Policies const& policies, mpl::false_, int)
+ inline object make_getter(D* d, Policies const& policies, detail::false_, int)
{
return python::make_function(
detail::datum<D>(d), policies, mpl::vector1<D&>()
@@ -169,18 +162,18 @@ namespace detail
// Handle non-member pointers without policies
template <class D>
- inline object make_getter(D* d, not_specified, mpl::false_, long)
+ inline object make_getter(D* d, not_specified, detail::false_, long)
{
typedef typename default_datum_getter_policy<D>::type policies;
- return detail::make_getter(d, policies(), mpl::false_(), 0);
+ return detail::make_getter(d, policies(), detail::false_(), 0);
}
// Handle pointers-to-members with policies
template <class C, class D, class Policies>
- inline object make_getter(D C::*pm, Policies const& policies, mpl::true_, int)
+ inline object make_getter(D C::*pm, Policies const& policies, detail::true_, int)
{
#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
- typedef typename remove_cv<C>::type Class;
+ typedef typename detail::remove_cv<C>::type Class;
#else
typedef C Class;
#endif
@@ -193,18 +186,18 @@ namespace detail
// Handle pointers-to-members without policies
template <class C, class D>
- inline object make_getter(D C::*pm, not_specified, mpl::true_, long)
+ inline object make_getter(D C::*pm, not_specified, detail::true_, long)
{
typedef typename default_member_getter_policy<D>::type policies;
- return detail::make_getter(pm, policies(), mpl::true_(), 0);
+ return detail::make_getter(pm, policies(), detail::true_(), 0);
}
// Handle references
template <class D, class P>
- inline object make_getter(D& d, P& p, mpl::false_, ...)
+ inline object make_getter(D& d, P& p, detail::false_, ...)
{
// Just dispatch to the handler for pointer types.
- return detail::make_getter(&d, p, mpl::false_(), 0L);
+ return detail::make_getter(&d, p, detail::false_(), 0L);
}
//
@@ -217,7 +210,7 @@ namespace detail
// Handle non-member pointers
template <class D, class Policies>
- inline object make_setter(D* p, Policies const& policies, mpl::false_, int)
+ inline object make_setter(D* p, Policies const& policies, detail::false_, int)
{
return python::make_function(
detail::datum<D>(p), policies, mpl::vector2<void,D const&>()
@@ -226,7 +219,7 @@ namespace detail
// Handle pointers-to-members
template <class C, class D, class Policies>
- inline object make_setter(D C::*pm, Policies const& policies, mpl::true_, int)
+ inline object make_setter(D C::*pm, Policies const& policies, detail::true_, int)
{
return python::make_function(
detail::member<D,C>(pm)
@@ -237,9 +230,9 @@ namespace detail
// Handle references
template <class D, class Policies>
- inline object make_setter(D& x, Policies const& policies, mpl::false_, ...)
+ inline object make_setter(D& x, Policies const& policies, detail::false_, ...)
{
- return detail::make_setter(&x, policies, mpl::false_(), 0L);
+ return detail::make_setter(&x, policies, detail::false_(), 0L);
}
}
@@ -253,13 +246,13 @@ namespace detail
template <class D, class Policies>
inline object make_getter(D& d, Policies const& policies)
{
- return detail::make_getter(d, policies, is_member_pointer<D>(), 0L);
+ return detail::make_getter(d, policies, detail::is_member_pointer<D>(), 0L);
}
template <class D, class Policies>
inline object make_getter(D const& d, Policies const& policies)
{
- return detail::make_getter(d, policies, is_member_pointer<D>(), 0L);
+ return detail::make_getter(d, policies, detail::is_member_pointer<D>(), 0L);
}
template <class D>
@@ -267,7 +260,7 @@ inline object make_getter(D& x)
{
detail::not_specified policy
= detail::not_specified(); // suppress a SunPro warning
- return detail::make_getter(x, policy, is_member_pointer<D>(), 0L);
+ return detail::make_getter(x, policy, detail::is_member_pointer<D>(), 0L);
}
# if !BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
@@ -276,7 +269,7 @@ inline object make_getter(D const& d)
{
detail::not_specified policy
= detail::not_specified(); // Suppress a SunPro warning
- return detail::make_getter(d, policy, is_member_pointer<D>(), 0L);
+ return detail::make_getter(d, policy, detail::is_member_pointer<D>(), 0L);
}
# endif
@@ -290,26 +283,26 @@ inline object make_getter(D const& d)
template <class D, class Policies>
inline object make_setter(D& x, Policies const& policies)
{
- return detail::make_setter(x, policies, is_member_pointer<D>(), 0);
+ return detail::make_setter(x, policies, detail::is_member_pointer<D>(), 0);
}
template <class D, class Policies>
inline object make_setter(D const& x, Policies const& policies)
{
- return detail::make_setter(x, policies, is_member_pointer<D>(), 0);
+ return detail::make_setter(x, policies, detail::is_member_pointer<D>(), 0);
}
template <class D>
inline object make_setter(D& x)
{
- return detail::make_setter(x, default_call_policies(), is_member_pointer<D>(), 0);
+ return detail::make_setter(x, default_call_policies(), detail::is_member_pointer<D>(), 0);
}
# if !BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
template <class D>
inline object make_setter(D const& x)
{
- return detail::make_setter(x, default_call_policies(), is_member_pointer<D>(), 0);
+ return detail::make_setter(x, default_call_policies(), detail::is_member_pointer<D>(), 0);
}
# endif
diff --git a/boost/python/default_call_policies.hpp b/boost/python/default_call_policies.hpp
index fcc242a924..c882257348 100644
--- a/boost/python/default_call_policies.hpp
+++ b/boost/python/default_call_policies.hpp
@@ -8,10 +8,8 @@
# include <boost/python/detail/prefix.hpp>
# include <boost/mpl/if.hpp>
# include <boost/python/to_python_value.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/python/detail/value_arg.hpp>
-# include <boost/type_traits/transform_traits.hpp>
-# include <boost/type_traits/is_pointer.hpp>
-# include <boost/type_traits/is_reference.hpp>
# include <boost/mpl/or.hpp>
# include <boost/mpl/front.hpp>
@@ -64,7 +62,7 @@ struct default_result_converter
struct apply
{
typedef typename mpl::if_<
- mpl::or_<is_pointer<R>, is_reference<R> >
+ mpl::or_<detail::is_pointer<R>, detail::is_reference<R> >
, detail::specify_a_return_value_policy_to_wrap_functions_returning<R>
, boost::python::to_python_value<
typename detail::value_arg<R>::type
diff --git a/boost/python/detail/borrowed_ptr.hpp b/boost/python/detail/borrowed_ptr.hpp
index d91d05c90f..7d78739ed9 100644
--- a/boost/python/detail/borrowed_ptr.hpp
+++ b/boost/python/detail/borrowed_ptr.hpp
@@ -8,8 +8,7 @@
# include <boost/config.hpp>
# include <boost/type.hpp>
# include <boost/mpl/if.hpp>
-# include <boost/type_traits/object_traits.hpp>
-# include <boost/type_traits/cv_traits.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/python/tag.hpp>
namespace boost { namespace python { namespace detail {
diff --git a/boost/python/detail/caller.hpp b/boost/python/detail/caller.hpp
index e479bf427d..c572d35aa9 100644
--- a/boost/python/detail/caller.hpp
+++ b/boost/python/detail/caller.hpp
@@ -16,6 +16,7 @@
# include <boost/python/detail/invoke.hpp>
# include <boost/python/detail/signature.hpp>
# include <boost/python/detail/preprocessor.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/python/arg_from_python.hpp>
# include <boost/python/converter/context_result_converter.hpp>
@@ -31,9 +32,6 @@
# include <boost/compressed_pair.hpp>
-# include <boost/type_traits/is_same.hpp>
-# include <boost/type_traits/is_convertible.hpp>
-
# include <boost/mpl/apply.hpp>
# include <boost/mpl/eval_if.hpp>
# include <boost/mpl/identity.hpp>
@@ -236,7 +234,7 @@ struct caller_arity<N>
typedef typename select_result_converter<Policies, rtype>::type result_converter;
static const signature_element ret = {
- (boost::is_void<rtype>::value ? "void" : type_id<rtype>().name())
+ (is_void<rtype>::value ? "void" : type_id<rtype>().name())
, &detail::converter_target_type<result_converter>::get_pytype
, boost::detail::indirect_traits::is_reference_to_non_const<rtype>::value
};
diff --git a/boost/python/detail/config.hpp b/boost/python/detail/config.hpp
index c92ecb32b0..3e4b7c9e54 100644
--- a/boost/python/detail/config.hpp
+++ b/boost/python/detail/config.hpp
@@ -105,7 +105,11 @@
// Set the name of our library, this will get undef'ed by auto_link.hpp
// once it's done with it:
//
-#define BOOST_LIB_NAME boost_python
+#if PY_MAJOR_VERSION == 2
+# define BOOST_LIB_NAME boost_python
+#elif PY_MAJOR_VERSION == 3
+# define BOOST_LIB_NAME boost_python3
+#endif
//
// If we're importing code from a dll, then tell auto_link.hpp about it:
//
diff --git a/boost/python/detail/convertible.hpp b/boost/python/detail/convertible.hpp
index 2ce552f5f7..1ff350ec24 100755
--- a/boost/python/detail/convertible.hpp
+++ b/boost/python/detail/convertible.hpp
@@ -7,11 +7,11 @@
# if defined(__EDG_VERSION__) && __EDG_VERSION__ <= 241
# include <boost/mpl/if.hpp>
-# include <boost/type_traits/conversion_traits.hpp>
+# include <boost/python/detail/type_traits.hpp>
# endif
// Supplies a runtime is_convertible check which can be used with tag
-// dispatching to work around the Metrowerks Pro7 limitation with boost::is_convertible
+// dispatching to work around the Metrowerks Pro7 limitation with boost/std::is_convertible
namespace boost { namespace python { namespace detail {
typedef char* yes_convertible;
diff --git a/boost/python/detail/cv_category.hpp b/boost/python/detail/cv_category.hpp
index d32dd0fdbe..eb5a8eb9da 100644
--- a/boost/python/detail/cv_category.hpp
+++ b/boost/python/detail/cv_category.hpp
@@ -4,7 +4,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef CV_CATEGORY_DWA200222_HPP
# define CV_CATEGORY_DWA200222_HPP
-# include <boost/type_traits/cv_traits.hpp>
+# include <boost/python/detail/type_traits.hpp>
namespace boost { namespace python { namespace detail {
@@ -26,8 +26,8 @@ struct cv_category
// BOOST_STATIC_CONSTANT(bool, c = is_const<T>::value);
// BOOST_STATIC_CONSTANT(bool, v = is_volatile<T>::value);
typedef cv_tag<
- ::boost::is_const<T>::value
- , ::boost::is_volatile<T>::value
+ is_const<T>::value
+ , is_volatile<T>::value
> type;
};
diff --git a/boost/python/detail/dealloc.hpp b/boost/python/detail/dealloc.hpp
index f2d914b18c..ce07926ee1 100644
--- a/boost/python/detail/dealloc.hpp
+++ b/boost/python/detail/dealloc.hpp
@@ -1,4 +1,4 @@
-// Copyright Gottfried Ganßauge 2003.
+// Copyright Gottfried Ganßauge 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)
diff --git a/boost/python/detail/decorated_type_id.hpp b/boost/python/detail/decorated_type_id.hpp
index 535508b43d..2596f3104a 100644
--- a/boost/python/detail/decorated_type_id.hpp
+++ b/boost/python/detail/decorated_type_id.hpp
@@ -7,7 +7,7 @@
# include <boost/python/type_id.hpp>
# include <boost/python/detail/indirect_traits.hpp>
-# include <boost/type_traits/cv_traits.hpp>
+# include <boost/python/detail/type_traits.hpp>
namespace boost { namespace python { namespace detail {
diff --git a/boost/python/detail/def_helper.hpp b/boost/python/detail/def_helper.hpp
index 92db09ed7b..24f9c5cdb2 100644
--- a/boost/python/detail/def_helper.hpp
+++ b/boost/python/detail/def_helper.hpp
@@ -6,12 +6,11 @@
# define DEF_HELPER_DWA200287_HPP
# include <boost/python/args.hpp>
-# include <boost/type_traits/same_traits.hpp>
# include <boost/python/detail/indirect_traits.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/mpl/not.hpp>
# include <boost/mpl/and.hpp>
# include <boost/mpl/or.hpp>
-# include <boost/type_traits/add_reference.hpp>
# include <boost/mpl/lambda.hpp>
# include <boost/mpl/apply.hpp>
# include <boost/tuple/tuple.hpp>
@@ -73,7 +72,8 @@ namespace detail
struct tuple_extract_base_select
{
typedef typename Tuple::head_type head_type;
- typedef typename mpl::apply1<Predicate, typename add_reference<head_type>::type>::type match_t;
+ typedef typename mpl::apply1<Predicate,
+ typename add_lvalue_reference<head_type>::type>::type match_t;
BOOST_STATIC_CONSTANT(bool, match = match_t::value);
typedef typename tuple_extract_impl<match>::template apply<Tuple,Predicate> type;
};
diff --git a/boost/python/detail/defaults_def.hpp b/boost/python/detail/defaults_def.hpp
index 68799f83e6..a721b76794 100644
--- a/boost/python/detail/defaults_def.hpp
+++ b/boost/python/detail/defaults_def.hpp
@@ -12,7 +12,7 @@
#define DEFAULTS_DEF_JDG20020811_HPP
#include <boost/python/detail/defaults_gen.hpp>
-#include <boost/type_traits.hpp>
+#include <boost/python/detail/type_traits.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/size.hpp>
#include <boost/static_assert.hpp>
@@ -238,7 +238,7 @@ namespace detail
typedef typename OverloadsT::non_void_return_type non_void_return_type;
typedef typename mpl::if_c<
- boost::is_same<void, return_type>::value
+ is_same<void, return_type>::value
, void_return_type
, non_void_return_type
>::type stubs_type;
diff --git a/boost/python/detail/destroy.hpp b/boost/python/detail/destroy.hpp
index 3ea6455330..d35b2b536e 100644
--- a/boost/python/detail/destroy.hpp
+++ b/boost/python/detail/destroy.hpp
@@ -5,7 +5,7 @@
#ifndef DESTROY_DWA2002221_HPP
# define DESTROY_DWA2002221_HPP
-# include <boost/type_traits/is_array.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/detail/workaround.hpp>
namespace boost { namespace python { namespace detail {
@@ -30,7 +30,7 @@ struct value_destroyer<true>
for (T const volatile* p = first; p != first + sizeof(A)/sizeof(T); ++p)
{
value_destroyer<
- boost::is_array<T>::value
+ is_array<T>::value
>::execute(p);
}
}
@@ -48,7 +48,7 @@ inline void destroy_referent_impl(void* p, T& (*)())
// note: cv-qualification needed for MSVC6
// must come *before* T for metrowerks
value_destroyer<
- (boost::is_array<T>::value)
+ (is_array<T>::value)
>::execute((const volatile T*)p);
}
diff --git a/boost/python/detail/invoke.hpp b/boost/python/detail/invoke.hpp
index 939fa11818..4c5296ff12 100644
--- a/boost/python/detail/invoke.hpp
+++ b/boost/python/detail/invoke.hpp
@@ -11,8 +11,6 @@
# include <boost/python/detail/preprocessor.hpp>
# include <boost/python/detail/none.hpp>
-# include <boost/type_traits/is_member_function_pointer.hpp>
-
# include <boost/preprocessor/iterate.hpp>
# include <boost/preprocessor/facilities/intercept.hpp>
# include <boost/preprocessor/repetition/enum_trailing_params.hpp>
diff --git a/boost/python/detail/pointee.hpp b/boost/python/detail/pointee.hpp
index e18c1f49b6..e786b37626 100644
--- a/boost/python/detail/pointee.hpp
+++ b/boost/python/detail/pointee.hpp
@@ -5,7 +5,7 @@
#ifndef POINTEE_DWA2002323_HPP
# define POINTEE_DWA2002323_HPP
-# include <boost/type_traits/object_traits.hpp>
+# include <boost/python/detail/type_traits.hpp>
namespace boost { namespace python { namespace detail {
diff --git a/boost/python/detail/result.hpp b/boost/python/detail/result.hpp
index 8ccc3c5029..2390693a88 100644
--- a/boost/python/detail/result.hpp
+++ b/boost/python/detail/result.hpp
@@ -11,8 +11,8 @@
# include <boost/type.hpp>
# include <boost/python/detail/preprocessor.hpp>
+# include <boost/python/detail/type_traits.hpp>
-# include <boost/type_traits/object_traits.hpp>
# include <boost/mpl/if.hpp>
# include <boost/preprocessor/comma_if.hpp>
diff --git a/boost/python/detail/string_literal.hpp b/boost/python/detail/string_literal.hpp
index a56e72ec6b..0961ec7c4e 100644
--- a/boost/python/detail/string_literal.hpp
+++ b/boost/python/detail/string_literal.hpp
@@ -7,8 +7,7 @@
# include <cstddef>
# include <boost/type.hpp>
-# include <boost/type_traits/array_traits.hpp>
-# include <boost/type_traits/same_traits.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/mpl/bool.hpp>
# include <boost/detail/workaround.hpp>
diff --git a/boost/python/detail/translate_exception.hpp b/boost/python/detail/translate_exception.hpp
index df7ec2dd6c..877db2b2c6 100644
--- a/boost/python/detail/translate_exception.hpp
+++ b/boost/python/detail/translate_exception.hpp
@@ -6,11 +6,9 @@
# define TRANSLATE_EXCEPTION_TDS20091020_HPP
# include <boost/python/detail/exception_handler.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/call_traits.hpp>
-# include <boost/type_traits/add_const.hpp>
-# include <boost/type_traits/add_reference.hpp>
-# include <boost/type_traits/remove_reference.hpp>
# include <boost/function/function0.hpp>
@@ -33,7 +31,7 @@ struct translate_exception
typename add_const<ExceptionType>::type
>::type exception_non_ref;
# else
- typedef typename add_reference<
+ typedef typename add_lvalue_reference<
typename add_const<ExceptionType>::type
>::type exception_cref;
# endif
diff --git a/boost/python/detail/type_traits.hpp b/boost/python/detail/type_traits.hpp
new file mode 100644
index 0000000000..df940c7ea2
--- /dev/null
+++ b/boost/python/detail/type_traits.hpp
@@ -0,0 +1,110 @@
+// Copyright Shreyans Doshi 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_PYTHON_DETAIL_TYPE_TRAITS_HPP
+# define BOOST_PYTHON_DETAIL_TYPE_TRAITS_HPP
+
+
+#if __cplusplus < 201103L
+# include <boost/type_traits/transform_traits.hpp>
+# include <boost/type_traits/same_traits.hpp>
+# include <boost/type_traits/cv_traits.hpp>
+# include <boost/type_traits/is_polymorphic.hpp>
+# include <boost/type_traits/composite_traits.hpp>
+# include <boost/type_traits/conversion_traits.hpp>
+# include <boost/type_traits/add_pointer.hpp>
+# include <boost/type_traits/remove_pointer.hpp>
+# include <boost/type_traits/is_void.hpp>
+# include <boost/type_traits/object_traits.hpp>
+# include <boost/type_traits/add_lvalue_reference.hpp>
+# include <boost/type_traits/function_traits.hpp>
+# include <boost/type_traits/is_scalar.hpp>
+# include <boost/type_traits/alignment_traits.hpp>
+# include <boost/mpl/bool.hpp>
+#else
+# include <type_traits>
+#endif
+
+# include <boost/type_traits/is_base_and_derived.hpp>
+# include <boost/type_traits/alignment_traits.hpp>
+# include <boost/type_traits/has_trivial_copy.hpp>
+
+
+namespace boost { namespace python { namespace detail {
+
+#if __cplusplus < 201103L
+ using boost::alignment_of;
+ using boost::add_const;
+ using boost::add_cv;
+ using boost::add_lvalue_reference;
+ using boost::add_pointer;
+
+ using boost::is_array;
+ using boost::is_class;
+ using boost::is_const;
+ using boost::is_convertible;
+ using boost::is_enum;
+ using boost::is_function;
+ using boost::is_integral;
+ using boost::is_lvalue_reference;
+ using boost::is_member_function_pointer;
+ using boost::is_member_pointer;
+ using boost::is_pointer;
+ using boost::is_polymorphic;
+ using boost::is_reference;
+ using boost::is_same;
+ using boost::is_scalar;
+ using boost::is_union;
+ using boost::is_void;
+ using boost::is_volatile;
+
+ using boost::remove_reference;
+ using boost::remove_pointer;
+ using boost::remove_cv;
+ using boost::remove_const;
+
+ using boost::mpl::true_;
+ using boost::mpl::false_;
+#else
+ using std::alignment_of;
+ using std::add_const;
+ using std::add_cv;
+ using std::add_lvalue_reference;
+ using std::add_pointer;
+
+ using std::is_array;
+ using std::is_class;
+ using std::is_const;
+ using std::is_convertible;
+ using std::is_enum;
+ using std::is_function;
+ using std::is_integral;
+ using std::is_lvalue_reference;
+ using std::is_member_function_pointer;
+ using std::is_member_pointer;
+ using std::is_pointer;
+ using std::is_polymorphic;
+ using std::is_reference;
+ using std::is_same;
+ using std::is_scalar;
+ using std::is_union;
+ using std::is_void;
+ using std::is_volatile;
+
+ using std::remove_reference;
+ using std::remove_pointer;
+ using std::remove_cv;
+ using std::remove_const;
+
+ using true_ = std::integral_constant<bool, true>;
+ using false_ = std::integral_constant<bool, false>;
+#endif
+ using boost::is_base_and_derived;
+ using boost::type_with_alignment;
+ using boost::has_trivial_copy;
+}}} // namespace boost::python::detail
+
+
+#endif //BOOST_DETAIL_TYPE_TRAITS_HPP
diff --git a/boost/python/detail/unwind_type.hpp b/boost/python/detail/unwind_type.hpp
index 9a997c9dbd..f6cdab64fe 100755
--- a/boost/python/detail/unwind_type.hpp
+++ b/boost/python/detail/unwind_type.hpp
@@ -7,7 +7,7 @@
# include <boost/python/detail/cv_category.hpp>
# include <boost/python/detail/indirect_traits.hpp>
-# include <boost/type_traits/object_traits.hpp>
+# include <boost/python/detail/type_traits.hpp>
namespace boost { namespace python { namespace detail {
@@ -155,10 +155,10 @@ unwind_type(boost::type<U>*p =0, Generator* =0)
#endif
{
BOOST_STATIC_CONSTANT(int, indirection
- = (boost::is_pointer<U>::value ? pointer_ : 0)
+ = (is_pointer<U>::value ? pointer_ : 0)
+ (indirect_traits::is_reference_to_pointer<U>::value
? reference_to_pointer_
- : boost::is_reference<U>::value
+ : is_lvalue_reference<U>::value
? reference_
: 0));
diff --git a/boost/python/detail/value_arg.hpp b/boost/python/detail/value_arg.hpp
index 747588d6fd..2c938dacca 100755
--- a/boost/python/detail/value_arg.hpp
+++ b/boost/python/detail/value_arg.hpp
@@ -6,8 +6,7 @@
# include <boost/python/detail/copy_ctor_mutates_rhs.hpp>
# include <boost/mpl/if.hpp>
-# include <boost/type_traits/add_reference.hpp>
-# include <boost/type_traits/add_const.hpp>
+# include <boost/python/detail/indirect_traits.hpp>
namespace boost { namespace python { namespace detail {
@@ -16,7 +15,7 @@ struct value_arg
: mpl::if_<
copy_ctor_mutates_rhs<T>
, T
- , typename add_reference<
+ , typename add_lvalue_reference<
typename add_const<T>::type
>::type
>
diff --git a/boost/python/detail/value_is_xxx.hpp b/boost/python/detail/value_is_xxx.hpp
index fbb9defd0b..e270f89ca3 100644
--- a/boost/python/detail/value_is_xxx.hpp
+++ b/boost/python/detail/value_is_xxx.hpp
@@ -9,11 +9,11 @@
# include <boost/mpl/bool.hpp>
# include <boost/preprocessor/enum_params.hpp>
-
-# include <boost/type_traits/remove_reference.hpp>
-# include <boost/type_traits/remove_cv.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/python/detail/is_xxx.hpp>
+namespace boost { namespace python { namespace detail {
+
# define BOOST_PYTHON_VALUE_IS_XXX_DEF(name, qualified_name, nargs) \
template <class X_> \
struct value_is_##name \
@@ -24,9 +24,10 @@ struct value_is_##name \
typename remove_reference<X_>::type \
>::type \
>::value); \
- typedef mpl::bool_<value> type; \
+ typedef mpl::bool_<value> type; \
\
};
+}}} // namespace boost::python::detail
#endif // VALUE_IS_XXX_DWA2003224_HPP
diff --git a/boost/python/detail/void_ptr.hpp b/boost/python/detail/void_ptr.hpp
index 06f680104d..5543b23a4a 100644
--- a/boost/python/detail/void_ptr.hpp
+++ b/boost/python/detail/void_ptr.hpp
@@ -5,7 +5,7 @@
#ifndef VOID_PTR_DWA200239_HPP
# define VOID_PTR_DWA200239_HPP
-# include <boost/type_traits/remove_cv.hpp>
+# include <boost/python/detail/type_traits.hpp>
namespace boost { namespace python { namespace detail {
diff --git a/boost/python/detail/wrapper_base.hpp b/boost/python/detail/wrapper_base.hpp
index 2a79e0c528..60ac99436e 100644
--- a/boost/python/detail/wrapper_base.hpp
+++ b/boost/python/detail/wrapper_base.hpp
@@ -5,8 +5,7 @@
# define WRAPPER_BASE_DWA2004722_HPP
# include <boost/python/detail/prefix.hpp>
-# include <boost/type_traits/is_polymorphic.hpp>
-# include <boost/mpl/bool.hpp>
+# include <boost/python/detail/type_traits.hpp>
namespace boost { namespace python {
@@ -21,14 +20,14 @@ namespace detail
inline PyObject* get_owner(wrapper_base const volatile& w);
inline PyObject*
- owner_impl(void const volatile* /*x*/, mpl::false_)
+ owner_impl(void const volatile* /*x*/, detail::false_)
{
return 0;
}
template <class T>
inline PyObject*
- owner_impl(T const volatile* x, mpl::true_);
+ owner_impl(T const volatile* x, detail::true_);
template <class T>
inline PyObject*
@@ -59,7 +58,7 @@ namespace detail
{
template <class T>
inline PyObject*
- owner_impl(T const volatile* x, mpl::true_)
+ owner_impl(T const volatile* x, detail::true_)
{
if (wrapper_base const volatile* w = dynamic_cast<wrapper_base const volatile*>(x))
{
diff --git a/boost/python/exec.hpp b/boost/python/exec.hpp
index 3ed1e15ce9..32a74991a7 100644
--- a/boost/python/exec.hpp
+++ b/boost/python/exec.hpp
@@ -20,6 +20,10 @@ object
BOOST_PYTHON_DECL
eval(str string, object global = object(), object local = object());
+object
+BOOST_PYTHON_DECL
+eval(char const *string, object global = object(), object local = object());
+
// Execute an individual python statement from str.
// global and local are the global and local scopes respectively,
// used during execution.
@@ -27,6 +31,10 @@ object
BOOST_PYTHON_DECL
exec_statement(str string, object global = object(), object local = object());
+object
+BOOST_PYTHON_DECL
+exec_statement(char const *string, object global = object(), object local = object());
+
// Execute python source code from str.
// global and local are the global and local scopes respectively,
// used during execution.
@@ -34,6 +42,10 @@ object
BOOST_PYTHON_DECL
exec(str string, object global = object(), object local = object());
+object
+BOOST_PYTHON_DECL
+exec(char const *string, object global = object(), object local = object());
+
// Execute python source code from file filename.
// global and local are the global and local scopes respectively,
// used during execution.
@@ -41,6 +53,10 @@ object
BOOST_PYTHON_DECL
exec_file(str filename, object global = object(), object local = object());
+object
+BOOST_PYTHON_DECL
+exec_file(char const *filename, object global = object(), object local = object());
+
}
}
diff --git a/boost/python/init.hpp b/boost/python/init.hpp
index 792de58e80..0ee763cc26 100644
--- a/boost/python/init.hpp
+++ b/boost/python/init.hpp
@@ -27,7 +27,7 @@
#include <boost/mpl/joint_view.hpp>
#include <boost/mpl/back.hpp>
-#include <boost/type_traits/is_same.hpp>
+#include <boost/python/detail/type_traits.hpp>
#include <boost/preprocessor/enum_params_with_a_default.hpp>
#include <boost/preprocessor/enum_params.hpp>
diff --git a/boost/python/iterator.hpp b/boost/python/iterator.hpp
index a64a920735..7c06ca2320 100644
--- a/boost/python/iterator.hpp
+++ b/boost/python/iterator.hpp
@@ -8,12 +8,10 @@
# include <boost/python/detail/prefix.hpp>
# include <boost/python/detail/target.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/python/object/iterator.hpp>
# include <boost/python/object_core.hpp>
-# include <boost/type_traits/cv_traits.hpp>
-# include <boost/type_traits/transform_traits.hpp>
-
# if defined(BOOST_MSVC) && (BOOST_MSVC == 1400) /*
> warning C4180: qualifier applied to function type has no meaning; ignored
Peter Dimov wrote:
@@ -80,7 +78,7 @@ namespace detail
template <class T>
struct iterators
: detail::iterators_impl<
- boost::is_const<T>::value
+ detail::is_const<T>::value
>::template apply<T>
{
};
diff --git a/boost/python/lvalue_from_pytype.hpp b/boost/python/lvalue_from_pytype.hpp
index e15dfbbb85..59d31b89cf 100644
--- a/boost/python/lvalue_from_pytype.hpp
+++ b/boost/python/lvalue_from_pytype.hpp
@@ -13,6 +13,7 @@
# include <boost/python/type_id.hpp>
# include <boost/python/converter/registry.hpp>
# include <boost/python/detail/void_ptr.hpp>
+# include <boost/python/detail/type_traits.hpp>
namespace boost { namespace python {
@@ -35,7 +36,7 @@ namespace detail
{
static inline void* execute(PyObject* op)
{
- typedef typename boost::add_reference<U>::type param;
+ typedef typename add_lvalue_reference<U>::type param;
return &Extractor::execute(
boost::python::detail::void_ptr_to_reference(
op, (param(*)())0 )
diff --git a/boost/python/make_constructor.hpp b/boost/python/make_constructor.hpp
index 92a7951d35..053d050cd6 100644
--- a/boost/python/make_constructor.hpp
+++ b/boost/python/make_constructor.hpp
@@ -43,19 +43,19 @@ namespace detail
private:
template <class U>
- void dispatch(U* x, mpl::true_) const
+ void dispatch(U* x, detail::true_) const
{
#if __cplusplus < 201103L
std::auto_ptr<U> owner(x);
- dispatch(owner, mpl::false_());
+ dispatch(owner, detail::false_());
#else
std::unique_ptr<U> owner(x);
- dispatch(std::move(owner), mpl::false_());
+ dispatch(std::move(owner), detail::false_());
#endif
}
template <class Ptr>
- void dispatch(Ptr x, mpl::false_) const
+ void dispatch(Ptr x, detail::false_) const
{
typedef typename pointee<Ptr>::type value_type;
typedef objects::pointer_holder<Ptr,value_type> holder;
diff --git a/boost/python/manage_new_object.hpp b/boost/python/manage_new_object.hpp
index 9585b13a6f..9ff341c1ac 100644
--- a/boost/python/manage_new_object.hpp
+++ b/boost/python/manage_new_object.hpp
@@ -7,9 +7,9 @@
# include <boost/python/detail/prefix.hpp>
# include <boost/python/detail/indirect_traits.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/mpl/if.hpp>
# include <boost/python/to_python_indirect.hpp>
-# include <boost/type_traits/composite_traits.hpp>
namespace boost { namespace python {
@@ -29,7 +29,7 @@ struct manage_new_object
struct apply
{
typedef typename mpl::if_c<
- boost::is_pointer<T>::value
+ detail::is_pointer<T>::value
, to_python_indirect<T, detail::make_owning_holder>
, detail::manage_new_object_requires_a_pointer_return_type<T>
>::type type;
diff --git a/boost/python/numeric.hpp b/boost/python/numeric.hpp
deleted file mode 100644
index ab4db8c32e..0000000000
--- a/boost/python/numeric.hpp
+++ /dev/null
@@ -1,242 +0,0 @@
-// 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)
-#ifndef NUMARRAY_DWA2002922_HPP
-# define NUMARRAY_DWA2002922_HPP
-
-# include <boost/python/detail/prefix.hpp>
-
-# include <boost/python/tuple.hpp>
-# include <boost/python/str.hpp>
-# include <boost/preprocessor/iteration/local.hpp>
-# include <boost/preprocessor/cat.hpp>
-# include <boost/preprocessor/repetition/enum.hpp>
-# include <boost/preprocessor/repetition/enum_params.hpp>
-# include <boost/preprocessor/repetition/enum_binary_params.hpp>
-
-namespace boost { namespace python { namespace numeric {
-
-class array;
-
-namespace aux
-{
- struct BOOST_PYTHON_DECL array_base : object
- {
-# define BOOST_PP_LOCAL_MACRO(n) \
- array_base(BOOST_PP_ENUM_PARAMS_Z(1, n, object const& x));
-# define BOOST_PP_LOCAL_LIMITS (1, 7)
-# include BOOST_PP_LOCAL_ITERATE()
-
- object argmax(long axis=-1);
- object argmin(long axis=-1);
- object argsort(long axis=-1);
- object astype(object const& type = object());
- void byteswap();
- object copy() const;
- object diagonal(long offset = 0, long axis1 = 0, long axis2 = 1) const;
- void info() const;
- bool is_c_array() const;
- bool isbyteswapped() const;
- array new_(object type) const;
- void sort();
- object trace(long offset = 0, long axis1 = 0, long axis2 = 1) const;
- object type() const;
- char typecode() const;
-
- object factory(
- object const& sequence = object()
- , object const& typecode = object()
- , bool copy = true
- , bool savespace = false
- , object type = object()
- , object shape = object());
-
- object getflat() const;
- long getrank() const;
- object getshape() const;
- bool isaligned() const;
- bool iscontiguous() const;
- long itemsize() const;
- long nelements() const;
- object nonzero() const;
-
- void put(object const& indices, object const& values);
-
- void ravel();
-
- object repeat(object const& repeats, long axis=0);
-
- void resize(object const& shape);
-
- void setflat(object const& flat);
- void setshape(object const& shape);
-
- void swapaxes(long axis1, long axis2);
-
- object take(object const& sequence, long axis = 0) const;
-
- void tofile(object const& file) const;
-
- str tostring() const;
-
- void transpose(object const& axes = object());
-
- object view() const;
-
- public: // implementation detail - do not touch.
- BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(array_base, object);
- };
-
- struct BOOST_PYTHON_DECL array_object_manager_traits
- {
- static bool check(PyObject* obj);
- static detail::new_non_null_reference adopt(PyObject* obj);
- static PyTypeObject const* get_pytype() ;
- };
-} // namespace aux
-
-class array : public aux::array_base
-{
- typedef aux::array_base base;
- public:
-
- object astype() { return base::astype(); }
-
- template <class Type>
- object astype(Type const& type_)
- {
- return base::astype(object(type_));
- }
-
- template <class Type>
- array new_(Type const& type_) const
- {
- return base::new_(object(type_));
- }
-
- template <class Sequence>
- void resize(Sequence const& x)
- {
- base::resize(object(x));
- }
-
-# define BOOST_PP_LOCAL_MACRO(n) \
- void resize(BOOST_PP_ENUM_PARAMS_Z(1, n, long x)) \
- { \
- resize(make_tuple(BOOST_PP_ENUM_PARAMS_Z(1, n, x))); \
- }
-# define BOOST_PP_LOCAL_LIMITS (1, BOOST_PYTHON_MAX_ARITY)
-# include BOOST_PP_LOCAL_ITERATE()
-
- template <class Sequence>
- void setshape(Sequence const& x)
- {
- base::setshape(object(x));
- }
-
-# define BOOST_PP_LOCAL_MACRO(n) \
- void setshape(BOOST_PP_ENUM_PARAMS_Z(1, n, long x)) \
- { \
- setshape(make_tuple(BOOST_PP_ENUM_PARAMS_Z(1, n, x))); \
- }
-# define BOOST_PP_LOCAL_LIMITS (1, BOOST_PYTHON_MAX_ARITY)
-# include BOOST_PP_LOCAL_ITERATE()
-
- template <class Indices, class Values>
- void put(Indices const& indices, Values const& values)
- {
- base::put(object(indices), object(values));
- }
-
- template <class Sequence>
- object take(Sequence const& sequence, long axis = 0)
- {
- return base::take(object(sequence), axis);
- }
-
- template <class File>
- void tofile(File const& f) const
- {
- base::tofile(object(f));
- }
-
- object factory()
- {
- return base::factory();
- }
-
- template <class Sequence>
- object factory(Sequence const& sequence)
- {
- return base::factory(object(sequence));
- }
-
- template <class Sequence, class Typecode>
- object factory(
- Sequence const& sequence
- , Typecode const& typecode_
- , bool copy = true
- , bool savespace = false
- )
- {
- return base::factory(object(sequence), object(typecode_), copy, savespace);
- }
-
- template <class Sequence, class Typecode, class Type>
- object factory(
- Sequence const& sequence
- , Typecode const& typecode_
- , bool copy
- , bool savespace
- , Type const& type
- )
- {
- return base::factory(object(sequence), object(typecode_), copy, savespace, object(type));
- }
-
- template <class Sequence, class Typecode, class Type, class Shape>
- object factory(
- Sequence const& sequence
- , Typecode const& typecode_
- , bool copy
- , bool savespace
- , Type const& type
- , Shape const& shape
- )
- {
- return base::factory(object(sequence), object(typecode_), copy, savespace, object(type), object(shape));
- }
-
-# define BOOST_PYTHON_ENUM_AS_OBJECT(z, n, x) object(BOOST_PP_CAT(x,n))
-# define BOOST_PP_LOCAL_MACRO(n) \
- template <BOOST_PP_ENUM_PARAMS_Z(1, n, class T)> \
- explicit array(BOOST_PP_ENUM_BINARY_PARAMS_Z(1, n, T, const& x)) \
- : base(BOOST_PP_ENUM_1(n, BOOST_PYTHON_ENUM_AS_OBJECT, x)) \
- {}
-# define BOOST_PP_LOCAL_LIMITS (1, 7)
-# include BOOST_PP_LOCAL_ITERATE()
-# undef BOOST_PYTHON_AS_OBJECT
-
- static BOOST_PYTHON_DECL void set_module_and_type(char const* package_name = 0, char const* type_attribute_name = 0);
- static BOOST_PYTHON_DECL std::string get_module_name();
-
- public: // implementation detail -- for internal use only
- BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(array, base);
-};
-
-} // namespace boost::python::numeric
-
-namespace converter
-{
- template <>
- struct object_manager_traits< numeric::array >
- : numeric::aux::array_object_manager_traits
- {
- BOOST_STATIC_CONSTANT(bool, is_specialized = true);
- };
-}
-
-}} // namespace boost::python
-
-#endif // NUMARRAY_DWA2002922_HPP
diff --git a/boost/python/numpy/config.hpp b/boost/python/numpy/config.hpp
index 6f39d3ce86..97178906e0 100644
--- a/boost/python/numpy/config.hpp
+++ b/boost/python/numpy/config.hpp
@@ -62,7 +62,11 @@
// Set the name of our library, this will get undef'ed by auto_link.hpp
// once it's done with it:
//
-#define BOOST_LIB_NAME boost_numpy
+#if PY_MAJOR_VERSION == 2
+# define BOOST_LIB_NAME boost_numpy
+#elif PY_MAJOR_VERSION == 3
+# define BOOST_LIB_NAME boost_numpy3
+#endif
//
// If we're importing code from a dll, then tell auto_link.hpp about it:
//
@@ -75,4 +79,6 @@
#include <boost/config/auto_link.hpp>
#endif // auto-linking disabled
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
+
#endif // CONFIG_NUMPY20170215_H_
diff --git a/boost/python/numpy/dtype.hpp b/boost/python/numpy/dtype.hpp
index b9e95f9beb..4673745e57 100644
--- a/boost/python/numpy/dtype.hpp
+++ b/boost/python/numpy/dtype.hpp
@@ -13,11 +13,10 @@
*/
#include <boost/python.hpp>
-#include <boost/python/numpy/numpy_object_mgr_traits.hpp>
#include <boost/python/numpy/config.hpp>
-
+#include <boost/python/numpy/numpy_object_mgr_traits.hpp>
#include <boost/mpl/for_each.hpp>
-#include <boost/type_traits/add_pointer.hpp>
+#include <boost/python/detail/type_traits.hpp>
namespace boost { namespace python { namespace numpy {
@@ -90,7 +89,7 @@ struct builtin_dtype<T,true> {
};
template <>
-struct builtin_dtype<bool,true> {
+struct BOOST_NUMPY_DECL builtin_dtype<bool,true> {
static dtype get();
};
diff --git a/boost/python/numpy/internal.hpp b/boost/python/numpy/internal.hpp
index fed31cbb08..c24718f0ae 100644
--- a/boost/python/numpy/internal.hpp
+++ b/boost/python/numpy/internal.hpp
@@ -15,6 +15,7 @@
*/
#include <boost/python.hpp>
+#include <boost/python/numpy/config.hpp>
#ifdef BOOST_PYTHON_NUMPY_INTERNAL
#define NO_IMPORT_ARRAY
#define NO_IMPORT_UFUNC
diff --git a/boost/python/numpy/ndarray.hpp b/boost/python/numpy/ndarray.hpp
index e5b6a9e94b..98a4cb15a1 100644
--- a/boost/python/numpy/ndarray.hpp
+++ b/boost/python/numpy/ndarray.hpp
@@ -13,7 +13,7 @@
#include <boost/python.hpp>
#include <boost/utility/enable_if.hpp>
-#include <boost/type_traits/is_integral.hpp>
+#include <boost/python/detail/type_traits.hpp>
#include <boost/python/numpy/numpy_object_mgr_traits.hpp>
#include <boost/python/numpy/dtype.hpp>
#include <boost/python/numpy/config.hpp>
@@ -176,7 +176,7 @@ ndarray from_data_impl(void * data,
Container strides,
object const & owner,
bool writeable,
- typename boost::enable_if< boost::is_integral<typename Container::value_type> >::type * enabled = NULL)
+ typename boost::enable_if< boost::python::detail::is_integral<typename Container::value_type> >::type * enabled = NULL)
{
std::vector<Py_intptr_t> shape_(shape.begin(),shape.end());
std::vector<Py_intptr_t> strides_(strides.begin(), strides.end());
diff --git a/boost/python/object/class_metadata.hpp b/boost/python/object/class_metadata.hpp
index 8e750b85cf..93303ecb60 100644
--- a/boost/python/object/class_metadata.hpp
+++ b/boost/python/object/class_metadata.hpp
@@ -17,14 +17,11 @@
#include <boost/python/detail/force_instantiate.hpp>
#include <boost/python/detail/not_specified.hpp>
+#include <boost/python/detail/type_traits.hpp>
#include <boost/python/has_back_reference.hpp>
#include <boost/python/bases.hpp>
-#include <boost/type_traits/add_pointer.hpp>
-#include <boost/type_traits/is_convertible.hpp>
-#include <boost/type_traits/is_polymorphic.hpp>
-
#include <boost/mpl/if.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/bool.hpp>
@@ -35,9 +32,6 @@
#include <boost/mpl/single_view.hpp>
#include <boost/mpl/assert.hpp>
-#include <boost/type_traits/is_same.hpp>
-
-#include <boost/type_traits/is_convertible.hpp>
#include <boost/noncopyable.hpp>
#include <boost/detail/workaround.hpp>
@@ -56,7 +50,7 @@ struct register_base_of
template <class Base>
inline void operator()(Base*) const
{
- BOOST_MPL_ASSERT_NOT((is_same<Base,Derived>));
+ BOOST_MPL_ASSERT_NOT((boost::python::detail::is_same<Base,Derived>));
// Register the Base class
register_dynamic_id<Base>();
@@ -65,14 +59,14 @@ struct register_base_of
register_conversion<Derived,Base>(false);
// Register the down-cast, if appropriate.
- this->register_downcast((Base*)0, is_polymorphic<Base>());
+ this->register_downcast((Base*)0, boost::python::detail::is_polymorphic<Base>());
}
private:
- static inline void register_downcast(void*, mpl::false_) {}
+ static inline void register_downcast(void*, boost::python::detail::false_) {}
template <class Base>
- static inline void register_downcast(Base*, mpl::true_)
+ static inline void register_downcast(Base*, boost::python::detail::true_)
{
register_conversion<Base, Derived>(true);
}
@@ -98,7 +92,7 @@ inline void register_shared_ptr_from_python_and_casts(T*, Bases)
// interface to mpl::for_each to avoid an MSVC 6 bug.
//
register_dynamic_id<T>();
- mpl::for_each(register_base_of<T>(), (Bases*)0, (add_pointer<mpl::_>*)0);
+ mpl::for_each(register_base_of<T>(), (Bases*)0, (boost::python::detail::add_pointer<mpl::_>*)0);
}
//
@@ -109,7 +103,7 @@ struct select_held_type
: mpl::if_<
mpl::or_<
python::detail::specifies_bases<T>
- , is_same<T,noncopyable>
+ , boost::python::detail::is_same<T,noncopyable>
>
, Prev
, T
@@ -156,9 +150,9 @@ struct class_metadata
>::type bases;
typedef mpl::or_<
- is_same<X1,noncopyable>
- , is_same<X2,noncopyable>
- , is_same<X3,noncopyable>
+ boost::python::detail::is_same<X1,noncopyable>
+ , boost::python::detail::is_same<X2,noncopyable>
+ , boost::python::detail::is_same<X3,noncopyable>
> is_noncopyable;
//
@@ -167,11 +161,11 @@ struct class_metadata
// Compute the actual type that will be held in the Holder.
typedef typename mpl::if_<
- is_same<held_type_arg,python::detail::not_specified>, T, held_type_arg
+ boost::python::detail::is_same<held_type_arg,python::detail::not_specified>, T, held_type_arg
>::type held_type;
// Determine if the object will be held by value
- typedef mpl::bool_<is_convertible<held_type*,T*>::value> use_value_holder;
+ typedef mpl::bool_<boost::python::detail::is_convertible<held_type*,T*>::value> use_value_holder;
// Compute the "wrapped type", that is, if held_type is a smart
// pointer, we're talking about the pointee.
@@ -185,7 +179,7 @@ struct class_metadata
typedef mpl::bool_<
mpl::or_<
has_back_reference<T>
- , is_same<held_type_arg,T>
+ , boost::python::detail::is_same<held_type_arg,T>
, is_base_and_derived<T,wrapped>
>::value
> use_back_reference;
@@ -214,7 +208,7 @@ struct class_metadata
template <class T2>
inline static void register_aux(python::wrapper<T2>*)
{
- typedef typename mpl::not_<is_same<T2,wrapped> >::type use_callback;
+ typedef typename mpl::not_<boost::python::detail::is_same<T2,wrapped> >::type use_callback;
class_metadata::register_aux2((T2*)0, use_callback());
}
@@ -243,7 +237,7 @@ struct class_metadata
inline static void maybe_register_pointer_to_python(...) {}
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
- inline static void maybe_register_pointer_to_python(void*,void*,mpl::true_*)
+ inline static void maybe_register_pointer_to_python(void*,void*,mpl::true_*)
{
objects::copy_class_object(python::type_id<T>(), python::type_id<back_reference<T const &> >());
objects::copy_class_object(python::type_id<T>(), python::type_id<back_reference<T &> >());
diff --git a/boost/python/object/forward.hpp b/boost/python/object/forward.hpp
index 30613d8ebd..c6515bb55b 100644
--- a/boost/python/object/forward.hpp
+++ b/boost/python/object/forward.hpp
@@ -6,11 +6,9 @@
# define FORWARD_DWA20011215_HPP
# include <boost/mpl/if.hpp>
-# include <boost/type_traits/is_scalar.hpp>
-# include <boost/type_traits/add_const.hpp>
-# include <boost/type_traits/add_reference.hpp>
# include <boost/ref.hpp>
# include <boost/python/detail/value_arg.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/python/detail/copy_ctor_mutates_rhs.hpp>
# include <boost/mpl/or.hpp>
@@ -22,7 +20,8 @@ namespace boost { namespace python { namespace objects {
template <class T>
struct reference_to_value
{
- typedef typename add_reference<typename add_const<T>::type>::type reference;
+ typedef typename boost::python::detail::add_lvalue_reference<typename
+ boost::python::detail::add_const<T>::type>::type reference;
reference_to_value(reference x) : m_value(x) {}
reference get() const { return m_value; }
@@ -36,7 +35,7 @@ struct reference_to_value
template <class T>
struct forward
: mpl::if_<
- mpl::or_<python::detail::copy_ctor_mutates_rhs<T>, is_scalar<T> >
+ mpl::or_<python::detail::copy_ctor_mutates_rhs<T>, boost::python::detail::is_scalar<T> >
, T
, reference_to_value<T>
>
@@ -65,7 +64,7 @@ struct unforward_cref
template<typename T>
struct unforward_cref<reference_to_value<T> >
- : add_reference<typename add_const<T>::type>
+ : boost::python::detail::add_lvalue_reference<typename boost::python::detail::add_const<T>::type>
{
};
diff --git a/boost/python/object/inheritance.hpp b/boost/python/object/inheritance.hpp
index b49a0442e2..90e56f0c1d 100644
--- a/boost/python/object/inheritance.hpp
+++ b/boost/python/object/inheritance.hpp
@@ -8,9 +8,8 @@
# include <boost/python/type_id.hpp>
# include <boost/shared_ptr.hpp>
# include <boost/mpl/if.hpp>
-# include <boost/type_traits/is_polymorphic.hpp>
-# include <boost/type_traits/is_base_and_derived.hpp>
# include <boost/detail/workaround.hpp>
+# include <boost/python/detail/type_traits.hpp>
namespace boost { namespace python { namespace objects {
@@ -58,7 +57,7 @@ struct non_polymorphic_id_generator
template <class T>
struct dynamic_id_generator
: mpl::if_<
- boost::is_polymorphic<T>
+ boost::python::detail::is_polymorphic<T>
, boost::python::objects::polymorphic_id_generator<T>
, boost::python::objects::non_polymorphic_id_generator<T>
>
@@ -104,7 +103,7 @@ struct implicit_cast_generator
template <class Source, class Target>
struct cast_generator
: mpl::if_<
- is_base_and_derived<Target,Source>
+ boost::python::detail::is_base_and_derived<Target,Source>
, implicit_cast_generator<Source,Target>
, dynamic_cast_generator<Source,Target>
>
diff --git a/boost/python/object/instance.hpp b/boost/python/object/instance.hpp
index 9c28d6822d..27b91a1e5f 100644
--- a/boost/python/object/instance.hpp
+++ b/boost/python/object/instance.hpp
@@ -6,7 +6,7 @@
# define INSTANCE_DWA200295_HPP
# include <boost/python/detail/prefix.hpp>
-# include <boost/type_traits/alignment_traits.hpp>
+
# include <cstddef>
namespace boost { namespace python
@@ -25,8 +25,8 @@ struct instance
PyObject* weakrefs;
instance_holder* objects;
- typedef typename type_with_alignment<
- ::boost::alignment_of<Data>::value
+ typedef typename boost::python::detail::type_with_alignment<
+ boost::python::detail::alignment_of<Data>::value
>::type align_t;
union
diff --git a/boost/python/object/iterator.hpp b/boost/python/object/iterator.hpp
index db5224713f..e2f65721fb 100644
--- a/boost/python/object/iterator.hpp
+++ b/boost/python/object/iterator.hpp
@@ -6,6 +6,7 @@
# define ITERATOR_DWA2002510_HPP
# include <boost/python/detail/prefix.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/python/class.hpp>
# include <boost/python/return_value_policy.hpp>
@@ -24,10 +25,6 @@
# include <boost/type.hpp>
-# include <boost/type_traits/is_same.hpp>
-# include <boost/type_traits/add_reference.hpp>
-# include <boost/type_traits/add_const.hpp>
-
# include <boost/detail/iterator.hpp>
namespace boost { namespace python { namespace objects {
@@ -202,8 +199,8 @@ inline object make_iterator_function(
)
{
typedef typename Accessor1::result_type iterator;
- typedef typename add_const<iterator>::type iterator_const;
- typedef typename add_reference<iterator_const>::type iterator_cref;
+ typedef typename boost::python::detail::add_const<iterator>::type iterator_const;
+ typedef typename boost::python::detail::add_lvalue_reference<iterator_const>::type iterator_cref;
return detail::make_iterator_function(
get_start
diff --git a/boost/python/object/make_instance.hpp b/boost/python/object/make_instance.hpp
index 5f2630adc7..31ec08f7c3 100644
--- a/boost/python/object/make_instance.hpp
+++ b/boost/python/object/make_instance.hpp
@@ -9,10 +9,10 @@
# include <boost/python/object/instance.hpp>
# include <boost/python/converter/registered.hpp>
# include <boost/python/detail/decref_guard.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/python/detail/none.hpp>
# include <boost/mpl/assert.hpp>
# include <boost/mpl/or.hpp>
-# include <boost/type_traits/is_union.hpp>
namespace boost { namespace python { namespace objects {
@@ -24,7 +24,8 @@ struct make_instance_impl
template <class Arg>
static inline PyObject* execute(Arg& x)
{
- BOOST_MPL_ASSERT((mpl::or_<is_class<T>, is_union<T> >));
+ BOOST_MPL_ASSERT((mpl::or_<boost::python::detail::is_class<T>,
+ boost::python::detail::is_union<T> >));
PyTypeObject* type = Derived::get_class_object(x);
diff --git a/boost/python/object/make_ptr_instance.hpp b/boost/python/object/make_ptr_instance.hpp
index 3a28190293..21089c6b88 100644
--- a/boost/python/object/make_ptr_instance.hpp
+++ b/boost/python/object/make_ptr_instance.hpp
@@ -7,7 +7,7 @@
# include <boost/python/object/make_instance.hpp>
# include <boost/python/converter/registry.hpp>
-# include <boost/type_traits/is_polymorphic.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/get_pointer.hpp>
# include <boost/detail/workaround.hpp>
# include <typeinfo>
@@ -47,7 +47,7 @@ struct make_ptr_instance
return 0; // means "return None".
PyTypeObject* derived = get_derived_class_object(
- BOOST_DEDUCED_TYPENAME is_polymorphic<U>::type(), p);
+ BOOST_DEDUCED_TYPENAME boost::python::detail::is_polymorphic<U>::type(), p);
if (derived)
return derived;
@@ -55,7 +55,7 @@ struct make_ptr_instance
}
template <class U>
- static inline PyTypeObject* get_derived_class_object(mpl::true_, U const volatile* x)
+ static inline PyTypeObject* get_derived_class_object(boost::python::detail::true_, U const volatile* x)
{
converter::registration const* r = converter::registry::query(
type_info(typeid(*get_pointer(x)))
@@ -64,7 +64,7 @@ struct make_ptr_instance
}
template <class U>
- static inline PyTypeObject* get_derived_class_object(mpl::false_, U*)
+ static inline PyTypeObject* get_derived_class_object(boost::python::detail::false_, U*)
{
return 0;
}
diff --git a/boost/python/object/pointer_holder.hpp b/boost/python/object/pointer_holder.hpp
index b28cbd83c8..c5caefe62c 100644
--- a/boost/python/object/pointer_holder.hpp
+++ b/boost/python/object/pointer_holder.hpp
@@ -21,6 +21,7 @@
# include <boost/python/detail/wrapper_base.hpp>
# include <boost/python/detail/force_instantiate.hpp>
# include <boost/python/detail/preprocessor.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/mpl/if.hpp>
@@ -35,8 +36,6 @@
# include <boost/detail/workaround.hpp>
-# include <boost/type_traits/remove_const.hpp>
-
namespace boost { namespace python {
template <class T> class wrapper;
@@ -128,7 +127,7 @@ inline pointer_holder_back_reference<Pointer,Value>::pointer_holder_back_referen
template <class Pointer, class Value>
void* pointer_holder<Pointer, Value>::holds(type_info dst_t, bool null_ptr_only)
{
- typedef typename boost::remove_const< Value >::type non_const_value;
+ typedef typename boost::python::detail::remove_const< Value >::type non_const_value;
if (dst_t == python::type_id<Pointer>()
&& !(null_ptr_only && get_pointer(this->m_p))
diff --git a/boost/python/object_core.hpp b/boost/python/object_core.hpp
index 209310ffd7..16480d0d89 100644
--- a/boost/python/object_core.hpp
+++ b/boost/python/object_core.hpp
@@ -31,10 +31,7 @@
# include <boost/python/detail/is_xxx.hpp>
# include <boost/python/detail/string_literal.hpp>
# include <boost/python/detail/def_helper_fwd.hpp>
-
-# include <boost/type_traits/is_same.hpp>
-# include <boost/type_traits/is_convertible.hpp>
-# include <boost/type_traits/remove_reference.hpp>
+# include <boost/python/detail/type_traits.hpp>
namespace boost { namespace python {
@@ -165,7 +162,7 @@ namespace api
// It's too late to specify anything other than docstrings if
// the callable object is already wrapped.
BOOST_STATIC_ASSERT(
- (is_same<char const*,DocStringT>::value
+ (detail::is_same<char const*,DocStringT>::value
|| detail::is_string_literal<DocStringT const>::value));
objects::add_to_namespace(cl, name, this->derived_visitor(), helper.doc());
@@ -208,8 +205,8 @@ namespace api
template <class T, class U>
struct is_derived
- : is_convertible<
- typename remove_reference<T>::type*
+ : boost::python::detail::is_convertible<
+ typename detail::remove_reference<T>::type*
, U const*
>
{};
@@ -280,14 +277,14 @@ namespace api
struct object_initializer_impl
{
static PyObject*
- get(object const& x, mpl::true_)
+ get(object const& x, detail::true_)
{
return python::incref(x.ptr());
}
template <class T>
static PyObject*
- get(T const& x, mpl::false_)
+ get(T const& x, detail::false_)
{
return python::incref(converter::arg_to_python<T>(x).get());
}
@@ -298,7 +295,7 @@ namespace api
{
template <class Policies>
static PyObject*
- get(proxy<Policies> const& x, mpl::false_)
+ get(proxy<Policies> const& x, detail::false_)
{
return python::incref(x.operator object().ptr());
}
diff --git a/boost/python/opaque_pointer_converter.hpp b/boost/python/opaque_pointer_converter.hpp
index e95c49bbfe..120985202b 100644
--- a/boost/python/opaque_pointer_converter.hpp
+++ b/boost/python/opaque_pointer_converter.hpp
@@ -1,4 +1,4 @@
-// Copyright Gottfried Ganßauge 2003..2006.
+// Copyright Gottfried Ganßauge 2003..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)
@@ -13,14 +13,11 @@
# include <boost/python/to_python_converter.hpp>
# include <boost/python/converter/registrations.hpp>
# include <boost/python/detail/dealloc.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/python/detail/none.hpp>
# include <boost/python/type_id.hpp>
# include <boost/python/errors.hpp>
-# include <boost/type_traits/remove_pointer.hpp>
-# include <boost/type_traits/is_pointer.hpp>
-# include <boost/type_traits/is_void.hpp>
-
# include <boost/implicit_cast.hpp>
# include <boost/mpl/eval_if.hpp>
diff --git a/boost/python/pointee.hpp b/boost/python/pointee.hpp
index ab8bb87439..7ec01e0824 100644
--- a/boost/python/pointee.hpp
+++ b/boost/python/pointee.hpp
@@ -6,9 +6,7 @@
# define POINTEE_DWA2002323_HPP
# include <boost/python/detail/prefix.hpp>
-
-# include <boost/type_traits/object_traits.hpp>
-# include <boost/type_traits/remove_pointer.hpp>
+# include <boost/python/detail/type_traits.hpp>
namespace boost { namespace python {
@@ -17,7 +15,7 @@ namespace detail
template <bool is_ptr = true>
struct pointee_impl
{
- template <class T> struct apply : remove_pointer<T> {};
+ template <class T> struct apply : detail::remove_pointer<T> {};
};
template <>
@@ -33,11 +31,11 @@ namespace detail
template <class T>
struct pointee
: detail::pointee_impl<
- ::boost::is_pointer<T>::value
+ detail::is_pointer<T>::value
>::template apply<T>
{
};
-}} // namespace boost::python::detail
+}} // namespace boost::python
#endif // POINTEE_DWA2002323_HPP
diff --git a/boost/python/reference_existing_object.hpp b/boost/python/reference_existing_object.hpp
index 8c2410715b..4c8344070b 100644
--- a/boost/python/reference_existing_object.hpp
+++ b/boost/python/reference_existing_object.hpp
@@ -9,7 +9,7 @@
# include <boost/python/detail/indirect_traits.hpp>
# include <boost/mpl/if.hpp>
# include <boost/python/to_python_indirect.hpp>
-# include <boost/type_traits/composite_traits.hpp>
+# include <boost/python/detail/type_traits.hpp>
namespace boost { namespace python {
@@ -31,7 +31,7 @@ struct reference_existing_object
struct apply
{
BOOST_STATIC_CONSTANT(
- bool, ok = is_pointer<T>::value || is_reference<T>::value);
+ bool, ok = detail::is_pointer<T>::value || detail::is_reference<T>::value);
typedef typename mpl::if_c<
ok
diff --git a/boost/python/return_arg.hpp b/boost/python/return_arg.hpp
index e869a58d12..de23993987 100644
--- a/boost/python/return_arg.hpp
+++ b/boost/python/return_arg.hpp
@@ -12,8 +12,7 @@
# include <boost/python/converter/pytype_function.hpp>
#endif
-# include <boost/type_traits/add_reference.hpp>
-# include <boost/type_traits/add_const.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/mpl/int.hpp>
# include <boost/mpl/at.hpp>
diff --git a/boost/python/return_by_value.hpp b/boost/python/return_by_value.hpp
index 593fc59cfe..42d7076d17 100644
--- a/boost/python/return_by_value.hpp
+++ b/boost/python/return_by_value.hpp
@@ -8,8 +8,7 @@
# include <boost/python/detail/prefix.hpp>
# include <boost/python/to_python_value.hpp>
-# include <boost/type_traits/add_reference.hpp>
-# include <boost/type_traits/add_const.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/python/detail/value_arg.hpp>
diff --git a/boost/python/return_opaque_pointer.hpp b/boost/python/return_opaque_pointer.hpp
index cf544d8030..4654e3bd51 100644
--- a/boost/python/return_opaque_pointer.hpp
+++ b/boost/python/return_opaque_pointer.hpp
@@ -1,4 +1,4 @@
-// Copyright Gottfried Ganßauge 2003.
+// Copyright Gottfried Ganßauge 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)
diff --git a/boost/python/signature.hpp b/boost/python/signature.hpp
index de4c512614..9b323a2823 100644
--- a/boost/python/signature.hpp
+++ b/boost/python/signature.hpp
@@ -14,9 +14,9 @@
# include <boost/python/detail/prefix.hpp>
# include <boost/mpl/if.hpp>
-# include <boost/type_traits/is_convertible.hpp>
# include <boost/python/detail/preprocessor.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <boost/preprocessor/repeat.hpp>
# include <boost/preprocessor/enum.hpp>
# include <boost/preprocessor/enum_params.hpp>
@@ -42,7 +42,7 @@ template <class C1, class C2>
struct most_derived
{
typedef typename mpl::if_<
- is_convertible<C1*,C2*>
+ detail::is_convertible<C1*,C2*>
, C1
, C2
>::type type;
diff --git a/boost/python/suite/indexing/detail/indexing_suite_detail.hpp b/boost/python/suite/indexing/detail/indexing_suite_detail.hpp
index 70df8a7273..eb8b81c0a3 100644
--- a/boost/python/suite/indexing/detail/indexing_suite_detail.hpp
+++ b/boost/python/suite/indexing/detail/indexing_suite_detail.hpp
@@ -11,7 +11,7 @@
# include <boost/get_pointer.hpp>
# include <boost/detail/binary_search.hpp>
# include <boost/numeric/conversion/cast.hpp>
-# include <boost/type_traits/is_pointer.hpp>
+# include <boost/python/detail/type_traits.hpp>
# include <vector>
# include <map>
#include <iostream>
@@ -465,14 +465,14 @@ namespace boost { namespace python { namespace detail {
template <class DataType>
static object
- base_get_item_helper(DataType const& p, mpl::true_)
+ base_get_item_helper(DataType const& p, detail::true_)
{
return object(ptr(p));
}
template <class DataType>
static object
- base_get_item_helper(DataType const& x, mpl::false_)
+ base_get_item_helper(DataType const& x, detail::false_)
{
return object(x);
}
diff --git a/boost/python/suite/indexing/indexing_suite.hpp b/boost/python/suite/indexing/indexing_suite.hpp
index 40301fdff5..3469a2a40f 100644
--- a/boost/python/suite/indexing/indexing_suite.hpp
+++ b/boost/python/suite/indexing/indexing_suite.hpp
@@ -14,7 +14,7 @@
# include <boost/python/iterator.hpp>
# include <boost/mpl/or.hpp>
# include <boost/mpl/not.hpp>
-# include <boost/type_traits/is_same.hpp>
+# include <boost/python/detail/type_traits.hpp>
namespace boost { namespace python {
@@ -122,10 +122,10 @@ namespace boost { namespace python {
mpl::bool_<NoProxy>
, mpl::not_<is_class<Data> >
, typename mpl::or_<
- is_same<Data, std::string>
- , is_same<Data, std::complex<float> >
- , is_same<Data, std::complex<double> >
- , is_same<Data, std::complex<long double> > >::type>
+ detail::is_same<Data, std::string>
+ , detail::is_same<Data, std::complex<float> >
+ , detail::is_same<Data, std::complex<double> >
+ , detail::is_same<Data, std::complex<long double> > >::type>
no_proxy;
typedef detail::container_element<Container, Index, DerivedPolicies>
diff --git a/boost/python/to_python_indirect.hpp b/boost/python/to_python_indirect.hpp
index af6ed33b9b..212e1db3d4 100644
--- a/boost/python/to_python_indirect.hpp
+++ b/boost/python/to_python_indirect.hpp
@@ -18,10 +18,7 @@
# include <boost/python/refcount.hpp>
-# include <boost/type_traits/is_pointer.hpp>
-# include <boost/type_traits/is_polymorphic.hpp>
-
-# include <boost/mpl/bool.hpp>
+# include <boost/python/detail/type_traits.hpp>
# if defined(__ICL) && __ICL < 600
# include <boost/shared_ptr.hpp>
@@ -38,7 +35,7 @@ struct to_python_indirect
inline PyObject*
operator()(U const& ref) const
{
- return this->execute(const_cast<U&>(ref), is_pointer<U>());
+ return this->execute(const_cast<U&>(ref), detail::is_pointer<U>());
}
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
inline PyTypeObject const*
@@ -49,20 +46,20 @@ struct to_python_indirect
#endif
private:
template <class U>
- inline PyObject* execute(U* ptr, mpl::true_) const
+ inline PyObject* execute(U* ptr, detail::true_) const
{
// No special NULL treatment for references
if (ptr == 0)
return python::detail::none();
else
- return this->execute(*ptr, mpl::false_());
+ return this->execute(*ptr, detail::false_());
}
template <class U>
- inline PyObject* execute(U const& x, mpl::false_) const
+ inline PyObject* execute(U const& x, detail::false_) const
{
U* const p = &const_cast<U&>(x);
- if (is_polymorphic<U>::value)
+ if (detail::is_polymorphic<U>::value)
{
if (PyObject* o = detail::wrapper_base_::owner(p))
return incref(o);
diff --git a/boost/python/to_python_value.hpp b/boost/python/to_python_value.hpp
index 2681f8a39c..2066d3a2ab 100644
--- a/boost/python/to_python_value.hpp
+++ b/boost/python/to_python_value.hpp
@@ -19,14 +19,12 @@
#include <boost/python/converter/object_manager.hpp>
#include <boost/python/converter/shared_ptr_to_python.hpp>
+#include <boost/python/detail/type_traits.hpp>
#include <boost/python/detail/value_is_shared_ptr.hpp>
#include <boost/python/detail/value_arg.hpp>
-#include <boost/type_traits/transform_traits.hpp>
-
#include <boost/mpl/if.hpp>
#include <boost/mpl/or.hpp>
-#include <boost/type_traits/is_const.hpp>
namespace boost { namespace python {
diff --git a/boost/python/type_id.hpp b/boost/python/type_id.hpp
index 38b7f7b453..601601c311 100644
--- a/boost/python/type_id.hpp
+++ b/boost/python/type_id.hpp
@@ -14,7 +14,7 @@
# include <ostream>
# include <boost/static_assert.hpp>
# include <boost/detail/workaround.hpp>
-# include <boost/type_traits/same_traits.hpp>
+# include <boost/python/detail/type_traits.hpp>
# ifndef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE
# if defined(__GNUC__) \
diff --git a/boost/qvm/detail/mat_assign.hpp b/boost/qvm/detail/mat_assign.hpp
new file mode 100644
index 0000000000..89d50243eb
--- /dev/null
+++ b/boost/qvm/detail/mat_assign.hpp
@@ -0,0 +1,75 @@
+//Copyright (c) 2008-2016 Emil Dotchevski and Reverge Studios, Inc.
+
+//Distributed under the 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 UUID_47136D2C385411E7BA27D3B681262D2E
+#define UUID_47136D2C385411E7BA27D3B681262D2E
+
+#include <boost/qvm/gen/mat_assign2.hpp>
+#include <boost/qvm/gen/mat_assign3.hpp>
+#include <boost/qvm/gen/mat_assign4.hpp>
+
+namespace
+boost
+ {
+ namespace
+ qvm
+ {
+ namespace
+ qvm_detail
+ {
+ template <int M,int N>
+ struct
+ assign_mm_defined
+ {
+ static bool const value=false;
+ };
+
+ template <int I,int N>
+ struct
+ copy_matrix_elements
+ {
+ template <class A,class B>
+ static
+ BOOST_QVM_INLINE_CRITICAL
+ void
+ f( A & a, B const & b )
+ {
+ mat_traits<A>::template write_element<I/mat_traits<A>::cols,I%mat_traits<A>::cols>(a) =
+ mat_traits<B>::template read_element<I/mat_traits<B>::cols,I%mat_traits<B>::cols>(b);
+ copy_matrix_elements<I+1,N>::f(a,b);
+ }
+ };
+
+ template <int N>
+ struct
+ copy_matrix_elements<N,N>
+ {
+ template <class A,class B>
+ static
+ BOOST_QVM_INLINE_CRITICAL
+ void
+ f( A &, B const & )
+ {
+ }
+ };
+ }
+
+ template <class A,class B>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename boost::enable_if_c<
+ is_mat<A>::value && is_mat<B>::value &&
+ mat_traits<A>::rows==mat_traits<B>::rows &&
+ mat_traits<A>::cols==mat_traits<B>::cols &&
+ !qvm_detail::assign_mm_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
+ A &>::type
+ assign( A & a, B const & b )
+ {
+ qvm_detail::copy_matrix_elements<0,mat_traits<A>::rows*mat_traits<A>::cols>::f(a,b);
+ return a;
+ }
+ }
+ }
+
+#endif
diff --git a/boost/qvm/detail/quat_assign.hpp b/boost/qvm/detail/quat_assign.hpp
new file mode 100644
index 0000000000..87b2cf1f62
--- /dev/null
+++ b/boost/qvm/detail/quat_assign.hpp
@@ -0,0 +1,35 @@
+//Copyright (c) 2008-2016 Emil Dotchevski and Reverge Studios, Inc.
+
+//Distributed under the 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 UUID_86A42DA4385511E7822024B881262D2E
+#define UUID_86A42DA4385511E7822024B881262D2E
+
+#include <boost/qvm/inline.hpp>
+#include <boost/qvm/enable_if.hpp>
+#include <boost/qvm/quat_traits.hpp>
+
+namespace
+boost
+ {
+ namespace
+ qvm
+ {
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename enable_if_c<
+ is_quat<A>::value && is_quat<B>::value,
+ A &>::type
+ assign( A & a, B const & b )
+ {
+ quat_traits<A>::template write_element<0>(a) = quat_traits<B>::template read_element<0>(b);
+ quat_traits<A>::template write_element<1>(a) = quat_traits<B>::template read_element<1>(b);
+ quat_traits<A>::template write_element<2>(a) = quat_traits<B>::template read_element<2>(b);
+ quat_traits<A>::template write_element<3>(a) = quat_traits<B>::template read_element<3>(b);
+ return a;
+ }
+ }
+ }
+
+#endif
diff --git a/boost/qvm/detail/vec_assign.hpp b/boost/qvm/detail/vec_assign.hpp
new file mode 100644
index 0000000000..c196c4f68d
--- /dev/null
+++ b/boost/qvm/detail/vec_assign.hpp
@@ -0,0 +1,71 @@
+//Copyright (c) 2008-2016 Emil Dotchevski and Reverge Studios, Inc.
+
+//Distributed under the 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 UUID_185557CE385511E780ACD7B781262D2E
+#define UUID_185557CE385511E780ACD7B781262D2E
+
+#include <boost/qvm/gen/vec_assign2.hpp>
+#include <boost/qvm/gen/vec_assign3.hpp>
+#include <boost/qvm/gen/vec_assign4.hpp>
+
+namespace
+boost
+ {
+ namespace
+ qvm
+ {
+ namespace
+ qvm_detail
+ {
+ template <int D>
+ struct
+ assign_vv_defined
+ {
+ static bool const value=false;
+ };
+
+ template <int I,int N>
+ struct
+ copy_vector_elements
+ {
+ template <class A,class B>
+ static
+ void
+ f( A & a, B const & b )
+ {
+ vec_traits<A>::template write_element<I>(a)=vec_traits<B>::template read_element<I>(b);
+ copy_vector_elements<I+1,N>::f(a,b);
+ }
+ };
+
+ template <int N>
+ struct
+ copy_vector_elements<N,N>
+ {
+ template <class A,class B>
+ static
+ void
+ f( A &, B const & )
+ {
+ }
+ };
+ }
+
+ template <class A,class B>
+ inline
+ typename boost::enable_if_c<
+ is_vec<A>::value && is_vec<B>::value &&
+ vec_traits<A>::dim==vec_traits<B>::dim &&
+ !qvm_detail::assign_vv_defined<vec_traits<A>::dim>::value,
+ A &>::type
+ assign( A & a, B const & b )
+ {
+ qvm_detail::copy_vector_elements<0,vec_traits<A>::dim>::f(a,b);
+ return a;
+ }
+ }
+ }
+
+#endif
diff --git a/boost/qvm/gen/mat_assign2.hpp b/boost/qvm/gen/mat_assign2.hpp
new file mode 100644
index 0000000000..8a4285c911
--- /dev/null
+++ b/boost/qvm/gen/mat_assign2.hpp
@@ -0,0 +1,125 @@
+//Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc.
+
+//Distributed under the 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_QVM_5DD4CBFC96F5453B13D89A1CDBAE32
+#define BOOST_QVM_5DD4CBFC96F5453B13D89A1CDBAE32
+
+//This file was generated by a program. Do not edit manually.
+
+#include <boost/qvm/enable_if.hpp>
+#include <boost/qvm/inline.hpp>
+#include <boost/qvm/mat_traits.hpp>
+
+namespace
+boost
+ {
+ namespace
+ qvm
+ {
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename enable_if_c<
+ mat_traits<A>::rows==2 && mat_traits<B>::rows==2 &&
+ mat_traits<A>::cols==2 && mat_traits<B>::cols==2,
+ A &>::type
+ assign( A & a, B const & b )
+ {
+ mat_traits<A>::template write_element<0,0>(a)=mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<A>::template write_element<0,1>(a)=mat_traits<B>::template read_element<0,1>(b);
+ mat_traits<A>::template write_element<1,0>(a)=mat_traits<B>::template read_element<1,0>(b);
+ mat_traits<A>::template write_element<1,1>(a)=mat_traits<B>::template read_element<1,1>(b);
+ return a;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::assign;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct assign_mm_defined;
+
+ template <>
+ struct
+ assign_mm_defined<2,2>
+ {
+ static bool const value=true;
+ };
+ }
+
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename enable_if_c<
+ mat_traits<A>::rows==2 && mat_traits<B>::rows==2 &&
+ mat_traits<A>::cols==1 && mat_traits<B>::cols==1,
+ A &>::type
+ assign( A & a, B const & b )
+ {
+ mat_traits<A>::template write_element<0,0>(a)=mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<A>::template write_element<1,0>(a)=mat_traits<B>::template read_element<1,0>(b);
+ return a;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::assign;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct assign_mm_defined;
+
+ template <>
+ struct
+ assign_mm_defined<2,1>
+ {
+ static bool const value=true;
+ };
+ }
+
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename enable_if_c<
+ mat_traits<A>::rows==1 && mat_traits<B>::rows==1 &&
+ mat_traits<A>::cols==2 && mat_traits<B>::cols==2,
+ A &>::type
+ assign( A & a, B const & b )
+ {
+ mat_traits<A>::template write_element<0,0>(a)=mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<A>::template write_element<0,1>(a)=mat_traits<B>::template read_element<0,1>(b);
+ return a;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::assign;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct assign_mm_defined;
+
+ template <>
+ struct
+ assign_mm_defined<1,2>
+ {
+ static bool const value=true;
+ };
+ }
+
+ }
+ }
+
+#endif
diff --git a/boost/qvm/gen/mat_assign3.hpp b/boost/qvm/gen/mat_assign3.hpp
new file mode 100644
index 0000000000..b2e8f12f4c
--- /dev/null
+++ b/boost/qvm/gen/mat_assign3.hpp
@@ -0,0 +1,132 @@
+//Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc.
+
+//Distributed under the 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_QVM_209A50EE407836FD124932F69E7D49DC
+#define BOOST_QVM_209A50EE407836FD124932F69E7D49DC
+
+//This file was generated by a program. Do not edit manually.
+
+#include <boost/qvm/enable_if.hpp>
+#include <boost/qvm/inline.hpp>
+#include <boost/qvm/mat_traits.hpp>
+
+namespace
+boost
+ {
+ namespace
+ qvm
+ {
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename enable_if_c<
+ mat_traits<A>::rows==3 && mat_traits<B>::rows==3 &&
+ mat_traits<A>::cols==3 && mat_traits<B>::cols==3,
+ A &>::type
+ assign( A & a, B const & b )
+ {
+ mat_traits<A>::template write_element<0,0>(a)=mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<A>::template write_element<0,1>(a)=mat_traits<B>::template read_element<0,1>(b);
+ mat_traits<A>::template write_element<0,2>(a)=mat_traits<B>::template read_element<0,2>(b);
+ mat_traits<A>::template write_element<1,0>(a)=mat_traits<B>::template read_element<1,0>(b);
+ mat_traits<A>::template write_element<1,1>(a)=mat_traits<B>::template read_element<1,1>(b);
+ mat_traits<A>::template write_element<1,2>(a)=mat_traits<B>::template read_element<1,2>(b);
+ mat_traits<A>::template write_element<2,0>(a)=mat_traits<B>::template read_element<2,0>(b);
+ mat_traits<A>::template write_element<2,1>(a)=mat_traits<B>::template read_element<2,1>(b);
+ mat_traits<A>::template write_element<2,2>(a)=mat_traits<B>::template read_element<2,2>(b);
+ return a;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::assign;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct assign_mm_defined;
+
+ template <>
+ struct
+ assign_mm_defined<3,3>
+ {
+ static bool const value=true;
+ };
+ }
+
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename enable_if_c<
+ mat_traits<A>::rows==3 && mat_traits<B>::rows==3 &&
+ mat_traits<A>::cols==1 && mat_traits<B>::cols==1,
+ A &>::type
+ assign( A & a, B const & b )
+ {
+ mat_traits<A>::template write_element<0,0>(a)=mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<A>::template write_element<1,0>(a)=mat_traits<B>::template read_element<1,0>(b);
+ mat_traits<A>::template write_element<2,0>(a)=mat_traits<B>::template read_element<2,0>(b);
+ return a;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::assign;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct assign_mm_defined;
+
+ template <>
+ struct
+ assign_mm_defined<3,1>
+ {
+ static bool const value=true;
+ };
+ }
+
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename enable_if_c<
+ mat_traits<A>::rows==1 && mat_traits<B>::rows==1 &&
+ mat_traits<A>::cols==3 && mat_traits<B>::cols==3,
+ A &>::type
+ assign( A & a, B const & b )
+ {
+ mat_traits<A>::template write_element<0,0>(a)=mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<A>::template write_element<0,1>(a)=mat_traits<B>::template read_element<0,1>(b);
+ mat_traits<A>::template write_element<0,2>(a)=mat_traits<B>::template read_element<0,2>(b);
+ return a;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::assign;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct assign_mm_defined;
+
+ template <>
+ struct
+ assign_mm_defined<1,3>
+ {
+ static bool const value=true;
+ };
+ }
+
+ }
+ }
+
+#endif
diff --git a/boost/qvm/gen/mat_assign4.hpp b/boost/qvm/gen/mat_assign4.hpp
new file mode 100644
index 0000000000..69fa3e1928
--- /dev/null
+++ b/boost/qvm/gen/mat_assign4.hpp
@@ -0,0 +1,141 @@
+//Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc.
+
+//Distributed under the 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_QVM_AD4F14F2444066D06BC430B7323BA122
+#define BOOST_QVM_AD4F14F2444066D06BC430B7323BA122
+
+//This file was generated by a program. Do not edit manually.
+
+#include <boost/qvm/enable_if.hpp>
+#include <boost/qvm/inline.hpp>
+#include <boost/qvm/mat_traits.hpp>
+
+namespace
+boost
+ {
+ namespace
+ qvm
+ {
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename enable_if_c<
+ mat_traits<A>::rows==4 && mat_traits<B>::rows==4 &&
+ mat_traits<A>::cols==4 && mat_traits<B>::cols==4,
+ A &>::type
+ assign( A & a, B const & b )
+ {
+ mat_traits<A>::template write_element<0,0>(a)=mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<A>::template write_element<0,1>(a)=mat_traits<B>::template read_element<0,1>(b);
+ mat_traits<A>::template write_element<0,2>(a)=mat_traits<B>::template read_element<0,2>(b);
+ mat_traits<A>::template write_element<0,3>(a)=mat_traits<B>::template read_element<0,3>(b);
+ mat_traits<A>::template write_element<1,0>(a)=mat_traits<B>::template read_element<1,0>(b);
+ mat_traits<A>::template write_element<1,1>(a)=mat_traits<B>::template read_element<1,1>(b);
+ mat_traits<A>::template write_element<1,2>(a)=mat_traits<B>::template read_element<1,2>(b);
+ mat_traits<A>::template write_element<1,3>(a)=mat_traits<B>::template read_element<1,3>(b);
+ mat_traits<A>::template write_element<2,0>(a)=mat_traits<B>::template read_element<2,0>(b);
+ mat_traits<A>::template write_element<2,1>(a)=mat_traits<B>::template read_element<2,1>(b);
+ mat_traits<A>::template write_element<2,2>(a)=mat_traits<B>::template read_element<2,2>(b);
+ mat_traits<A>::template write_element<2,3>(a)=mat_traits<B>::template read_element<2,3>(b);
+ mat_traits<A>::template write_element<3,0>(a)=mat_traits<B>::template read_element<3,0>(b);
+ mat_traits<A>::template write_element<3,1>(a)=mat_traits<B>::template read_element<3,1>(b);
+ mat_traits<A>::template write_element<3,2>(a)=mat_traits<B>::template read_element<3,2>(b);
+ mat_traits<A>::template write_element<3,3>(a)=mat_traits<B>::template read_element<3,3>(b);
+ return a;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::assign;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct assign_mm_defined;
+
+ template <>
+ struct
+ assign_mm_defined<4,4>
+ {
+ static bool const value=true;
+ };
+ }
+
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename enable_if_c<
+ mat_traits<A>::rows==4 && mat_traits<B>::rows==4 &&
+ mat_traits<A>::cols==1 && mat_traits<B>::cols==1,
+ A &>::type
+ assign( A & a, B const & b )
+ {
+ mat_traits<A>::template write_element<0,0>(a)=mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<A>::template write_element<1,0>(a)=mat_traits<B>::template read_element<1,0>(b);
+ mat_traits<A>::template write_element<2,0>(a)=mat_traits<B>::template read_element<2,0>(b);
+ mat_traits<A>::template write_element<3,0>(a)=mat_traits<B>::template read_element<3,0>(b);
+ return a;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::assign;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct assign_mm_defined;
+
+ template <>
+ struct
+ assign_mm_defined<4,1>
+ {
+ static bool const value=true;
+ };
+ }
+
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename enable_if_c<
+ mat_traits<A>::rows==1 && mat_traits<B>::rows==1 &&
+ mat_traits<A>::cols==4 && mat_traits<B>::cols==4,
+ A &>::type
+ assign( A & a, B const & b )
+ {
+ mat_traits<A>::template write_element<0,0>(a)=mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<A>::template write_element<0,1>(a)=mat_traits<B>::template read_element<0,1>(b);
+ mat_traits<A>::template write_element<0,2>(a)=mat_traits<B>::template read_element<0,2>(b);
+ mat_traits<A>::template write_element<0,3>(a)=mat_traits<B>::template read_element<0,3>(b);
+ return a;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::assign;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct assign_mm_defined;
+
+ template <>
+ struct
+ assign_mm_defined<1,4>
+ {
+ static bool const value=true;
+ };
+ }
+
+ }
+ }
+
+#endif
diff --git a/boost/qvm/gen/mat_operations2.hpp b/boost/qvm/gen/mat_operations2.hpp
index 6fbda7a800..d20339bc7d 100644
--- a/boost/qvm/gen/mat_operations2.hpp
+++ b/boost/qvm/gen/mat_operations2.hpp
@@ -1,4 +1,4 @@
-//Copyright (c) 2008-2016 Emil Dotchevski and Reverge Studios, Inc.
+//Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc.
//Distributed under the Boost Software License, Version 1.0. (See accompanying
//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -11,10 +11,8 @@
#include <boost/qvm/assert.hpp>
#include <boost/qvm/deduce_mat.hpp>
#include <boost/qvm/deduce_vec.hpp>
-#include <boost/qvm/enable_if.hpp>
#include <boost/qvm/error.hpp>
-#include <boost/qvm/inline.hpp>
-#include <boost/qvm/mat_traits.hpp>
+#include <boost/qvm/gen/mat_assign2.hpp>
#include <boost/qvm/throw_exception.hpp>
namespace
@@ -1029,107 +1027,6 @@ boost
};
}
- template <class A,class B>
- BOOST_QVM_INLINE_OPERATIONS
- typename enable_if_c<
- mat_traits<A>::rows==2 && mat_traits<B>::rows==2 &&
- mat_traits<A>::cols==2 && mat_traits<B>::cols==2,
- A &>::type
- assign( A & a, B const & b )
- {
- mat_traits<A>::template write_element<0,0>(a)=mat_traits<B>::template read_element<0,0>(b);
- mat_traits<A>::template write_element<0,1>(a)=mat_traits<B>::template read_element<0,1>(b);
- mat_traits<A>::template write_element<1,0>(a)=mat_traits<B>::template read_element<1,0>(b);
- mat_traits<A>::template write_element<1,1>(a)=mat_traits<B>::template read_element<1,1>(b);
- return a;
- }
-
- namespace
- sfinae
- {
- using ::boost::qvm::assign;
- }
-
- namespace
- qvm_detail
- {
- template <int R,int C>
- struct assign_mm_defined;
-
- template <>
- struct
- assign_mm_defined<2,2>
- {
- static bool const value=true;
- };
- }
-
- template <class A,class B>
- BOOST_QVM_INLINE_OPERATIONS
- typename enable_if_c<
- mat_traits<A>::rows==2 && mat_traits<B>::rows==2 &&
- mat_traits<A>::cols==1 && mat_traits<B>::cols==1,
- A &>::type
- assign( A & a, B const & b )
- {
- mat_traits<A>::template write_element<0,0>(a)=mat_traits<B>::template read_element<0,0>(b);
- mat_traits<A>::template write_element<1,0>(a)=mat_traits<B>::template read_element<1,0>(b);
- return a;
- }
-
- namespace
- sfinae
- {
- using ::boost::qvm::assign;
- }
-
- namespace
- qvm_detail
- {
- template <int R,int C>
- struct assign_mm_defined;
-
- template <>
- struct
- assign_mm_defined<2,1>
- {
- static bool const value=true;
- };
- }
-
- template <class A,class B>
- BOOST_QVM_INLINE_OPERATIONS
- typename enable_if_c<
- mat_traits<A>::rows==1 && mat_traits<B>::rows==1 &&
- mat_traits<A>::cols==2 && mat_traits<B>::cols==2,
- A &>::type
- assign( A & a, B const & b )
- {
- mat_traits<A>::template write_element<0,0>(a)=mat_traits<B>::template read_element<0,0>(b);
- mat_traits<A>::template write_element<0,1>(a)=mat_traits<B>::template read_element<0,1>(b);
- return a;
- }
-
- namespace
- sfinae
- {
- using ::boost::qvm::assign;
- }
-
- namespace
- qvm_detail
- {
- template <int R,int C>
- struct assign_mm_defined;
-
- template <>
- struct
- assign_mm_defined<1,2>
- {
- static bool const value=true;
- };
- }
-
template <class R,class A>
BOOST_QVM_INLINE_OPERATIONS
typename enable_if_c<
diff --git a/boost/qvm/gen/mat_operations3.hpp b/boost/qvm/gen/mat_operations3.hpp
index 5b0e74b458..31cf755dab 100644
--- a/boost/qvm/gen/mat_operations3.hpp
+++ b/boost/qvm/gen/mat_operations3.hpp
@@ -1,4 +1,4 @@
-//Copyright (c) 2008-2016 Emil Dotchevski and Reverge Studios, Inc.
+//Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc.
//Distributed under the Boost Software License, Version 1.0. (See accompanying
//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -11,10 +11,8 @@
#include <boost/qvm/assert.hpp>
#include <boost/qvm/deduce_mat.hpp>
#include <boost/qvm/deduce_vec.hpp>
-#include <boost/qvm/enable_if.hpp>
#include <boost/qvm/error.hpp>
-#include <boost/qvm/inline.hpp>
-#include <boost/qvm/mat_traits.hpp>
+#include <boost/qvm/gen/mat_assign3.hpp>
#include <boost/qvm/quat_traits.hpp>
#include <boost/qvm/scalar_traits.hpp>
#include <boost/qvm/throw_exception.hpp>
@@ -1100,114 +1098,6 @@ boost
};
}
- template <class A,class B>
- BOOST_QVM_INLINE_OPERATIONS
- typename enable_if_c<
- mat_traits<A>::rows==3 && mat_traits<B>::rows==3 &&
- mat_traits<A>::cols==3 && mat_traits<B>::cols==3,
- A &>::type
- assign( A & a, B const & b )
- {
- mat_traits<A>::template write_element<0,0>(a)=mat_traits<B>::template read_element<0,0>(b);
- mat_traits<A>::template write_element<0,1>(a)=mat_traits<B>::template read_element<0,1>(b);
- mat_traits<A>::template write_element<0,2>(a)=mat_traits<B>::template read_element<0,2>(b);
- mat_traits<A>::template write_element<1,0>(a)=mat_traits<B>::template read_element<1,0>(b);
- mat_traits<A>::template write_element<1,1>(a)=mat_traits<B>::template read_element<1,1>(b);
- mat_traits<A>::template write_element<1,2>(a)=mat_traits<B>::template read_element<1,2>(b);
- mat_traits<A>::template write_element<2,0>(a)=mat_traits<B>::template read_element<2,0>(b);
- mat_traits<A>::template write_element<2,1>(a)=mat_traits<B>::template read_element<2,1>(b);
- mat_traits<A>::template write_element<2,2>(a)=mat_traits<B>::template read_element<2,2>(b);
- return a;
- }
-
- namespace
- sfinae
- {
- using ::boost::qvm::assign;
- }
-
- namespace
- qvm_detail
- {
- template <int R,int C>
- struct assign_mm_defined;
-
- template <>
- struct
- assign_mm_defined<3,3>
- {
- static bool const value=true;
- };
- }
-
- template <class A,class B>
- BOOST_QVM_INLINE_OPERATIONS
- typename enable_if_c<
- mat_traits<A>::rows==3 && mat_traits<B>::rows==3 &&
- mat_traits<A>::cols==1 && mat_traits<B>::cols==1,
- A &>::type
- assign( A & a, B const & b )
- {
- mat_traits<A>::template write_element<0,0>(a)=mat_traits<B>::template read_element<0,0>(b);
- mat_traits<A>::template write_element<1,0>(a)=mat_traits<B>::template read_element<1,0>(b);
- mat_traits<A>::template write_element<2,0>(a)=mat_traits<B>::template read_element<2,0>(b);
- return a;
- }
-
- namespace
- sfinae
- {
- using ::boost::qvm::assign;
- }
-
- namespace
- qvm_detail
- {
- template <int R,int C>
- struct assign_mm_defined;
-
- template <>
- struct
- assign_mm_defined<3,1>
- {
- static bool const value=true;
- };
- }
-
- template <class A,class B>
- BOOST_QVM_INLINE_OPERATIONS
- typename enable_if_c<
- mat_traits<A>::rows==1 && mat_traits<B>::rows==1 &&
- mat_traits<A>::cols==3 && mat_traits<B>::cols==3,
- A &>::type
- assign( A & a, B const & b )
- {
- mat_traits<A>::template write_element<0,0>(a)=mat_traits<B>::template read_element<0,0>(b);
- mat_traits<A>::template write_element<0,1>(a)=mat_traits<B>::template read_element<0,1>(b);
- mat_traits<A>::template write_element<0,2>(a)=mat_traits<B>::template read_element<0,2>(b);
- return a;
- }
-
- namespace
- sfinae
- {
- using ::boost::qvm::assign;
- }
-
- namespace
- qvm_detail
- {
- template <int R,int C>
- struct assign_mm_defined;
-
- template <>
- struct
- assign_mm_defined<1,3>
- {
- static bool const value=true;
- };
- }
-
template <class R,class A>
BOOST_QVM_INLINE_OPERATIONS
typename enable_if_c<
diff --git a/boost/qvm/gen/mat_operations4.hpp b/boost/qvm/gen/mat_operations4.hpp
index ad115f916d..1c50131461 100644
--- a/boost/qvm/gen/mat_operations4.hpp
+++ b/boost/qvm/gen/mat_operations4.hpp
@@ -1,4 +1,4 @@
-//Copyright (c) 2008-2016 Emil Dotchevski and Reverge Studios, Inc.
+//Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc.
//Distributed under the Boost Software License, Version 1.0. (See accompanying
//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -11,10 +11,8 @@
#include <boost/qvm/assert.hpp>
#include <boost/qvm/deduce_mat.hpp>
#include <boost/qvm/deduce_vec.hpp>
-#include <boost/qvm/enable_if.hpp>
#include <boost/qvm/error.hpp>
-#include <boost/qvm/inline.hpp>
-#include <boost/qvm/mat_traits.hpp>
+#include <boost/qvm/gen/mat_assign4.hpp>
#include <boost/qvm/quat_traits.hpp>
#include <boost/qvm/scalar_traits.hpp>
#include <boost/qvm/throw_exception.hpp>
@@ -1189,123 +1187,6 @@ boost
};
}
- template <class A,class B>
- BOOST_QVM_INLINE_OPERATIONS
- typename enable_if_c<
- mat_traits<A>::rows==4 && mat_traits<B>::rows==4 &&
- mat_traits<A>::cols==4 && mat_traits<B>::cols==4,
- A &>::type
- assign( A & a, B const & b )
- {
- mat_traits<A>::template write_element<0,0>(a)=mat_traits<B>::template read_element<0,0>(b);
- mat_traits<A>::template write_element<0,1>(a)=mat_traits<B>::template read_element<0,1>(b);
- mat_traits<A>::template write_element<0,2>(a)=mat_traits<B>::template read_element<0,2>(b);
- mat_traits<A>::template write_element<0,3>(a)=mat_traits<B>::template read_element<0,3>(b);
- mat_traits<A>::template write_element<1,0>(a)=mat_traits<B>::template read_element<1,0>(b);
- mat_traits<A>::template write_element<1,1>(a)=mat_traits<B>::template read_element<1,1>(b);
- mat_traits<A>::template write_element<1,2>(a)=mat_traits<B>::template read_element<1,2>(b);
- mat_traits<A>::template write_element<1,3>(a)=mat_traits<B>::template read_element<1,3>(b);
- mat_traits<A>::template write_element<2,0>(a)=mat_traits<B>::template read_element<2,0>(b);
- mat_traits<A>::template write_element<2,1>(a)=mat_traits<B>::template read_element<2,1>(b);
- mat_traits<A>::template write_element<2,2>(a)=mat_traits<B>::template read_element<2,2>(b);
- mat_traits<A>::template write_element<2,3>(a)=mat_traits<B>::template read_element<2,3>(b);
- mat_traits<A>::template write_element<3,0>(a)=mat_traits<B>::template read_element<3,0>(b);
- mat_traits<A>::template write_element<3,1>(a)=mat_traits<B>::template read_element<3,1>(b);
- mat_traits<A>::template write_element<3,2>(a)=mat_traits<B>::template read_element<3,2>(b);
- mat_traits<A>::template write_element<3,3>(a)=mat_traits<B>::template read_element<3,3>(b);
- return a;
- }
-
- namespace
- sfinae
- {
- using ::boost::qvm::assign;
- }
-
- namespace
- qvm_detail
- {
- template <int R,int C>
- struct assign_mm_defined;
-
- template <>
- struct
- assign_mm_defined<4,4>
- {
- static bool const value=true;
- };
- }
-
- template <class A,class B>
- BOOST_QVM_INLINE_OPERATIONS
- typename enable_if_c<
- mat_traits<A>::rows==4 && mat_traits<B>::rows==4 &&
- mat_traits<A>::cols==1 && mat_traits<B>::cols==1,
- A &>::type
- assign( A & a, B const & b )
- {
- mat_traits<A>::template write_element<0,0>(a)=mat_traits<B>::template read_element<0,0>(b);
- mat_traits<A>::template write_element<1,0>(a)=mat_traits<B>::template read_element<1,0>(b);
- mat_traits<A>::template write_element<2,0>(a)=mat_traits<B>::template read_element<2,0>(b);
- mat_traits<A>::template write_element<3,0>(a)=mat_traits<B>::template read_element<3,0>(b);
- return a;
- }
-
- namespace
- sfinae
- {
- using ::boost::qvm::assign;
- }
-
- namespace
- qvm_detail
- {
- template <int R,int C>
- struct assign_mm_defined;
-
- template <>
- struct
- assign_mm_defined<4,1>
- {
- static bool const value=true;
- };
- }
-
- template <class A,class B>
- BOOST_QVM_INLINE_OPERATIONS
- typename enable_if_c<
- mat_traits<A>::rows==1 && mat_traits<B>::rows==1 &&
- mat_traits<A>::cols==4 && mat_traits<B>::cols==4,
- A &>::type
- assign( A & a, B const & b )
- {
- mat_traits<A>::template write_element<0,0>(a)=mat_traits<B>::template read_element<0,0>(b);
- mat_traits<A>::template write_element<0,1>(a)=mat_traits<B>::template read_element<0,1>(b);
- mat_traits<A>::template write_element<0,2>(a)=mat_traits<B>::template read_element<0,2>(b);
- mat_traits<A>::template write_element<0,3>(a)=mat_traits<B>::template read_element<0,3>(b);
- return a;
- }
-
- namespace
- sfinae
- {
- using ::boost::qvm::assign;
- }
-
- namespace
- qvm_detail
- {
- template <int R,int C>
- struct assign_mm_defined;
-
- template <>
- struct
- assign_mm_defined<1,4>
- {
- static bool const value=true;
- };
- }
-
template <class R,class A>
BOOST_QVM_INLINE_OPERATIONS
typename enable_if_c<
diff --git a/boost/qvm/gen/swizzle2.hpp b/boost/qvm/gen/swizzle2.hpp
index b894bb6986..a4f6ac27aa 100644
--- a/boost/qvm/gen/swizzle2.hpp
+++ b/boost/qvm/gen/swizzle2.hpp
@@ -1,10 +1,10 @@
-//Copyright (c) 2008-2016 Emil Dotchevski and Reverge Studios, Inc.
+//Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc.
//Distributed under the 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_QVM_61CDD11E9D9C167272E61DF0844F4A77
-#define BOOST_QVM_61CDD11E9D9C167272E61DF0844F4A77
+#ifndef BOOST_QVM_9673ED9162F6768D4F74A4AD0576876
+#define BOOST_QVM_9673ED9162F6768D4F74A4AD0576876
//This file was generated by a program. Do not edit manually.
diff --git a/boost/qvm/gen/swizzle3.hpp b/boost/qvm/gen/swizzle3.hpp
index f1f182d2bd..beacb2681e 100644
--- a/boost/qvm/gen/swizzle3.hpp
+++ b/boost/qvm/gen/swizzle3.hpp
@@ -1,10 +1,10 @@
-//Copyright (c) 2008-2016 Emil Dotchevski and Reverge Studios, Inc.
+//Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc.
//Distributed under the 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_QVM_2D7E8392C53CBC9121E33749ECF4D5
-#define BOOST_QVM_2D7E8392C53CBC9121E33749ECF4D5
+#ifndef BOOST_QVM_FA16BB11ADAE248879FE52DB2543E53C
+#define BOOST_QVM_FA16BB11ADAE248879FE52DB2543E53C
//This file was generated by a program. Do not edit manually.
diff --git a/boost/qvm/gen/swizzle4.hpp b/boost/qvm/gen/swizzle4.hpp
index 91ba215c8b..c400a12a6f 100644
--- a/boost/qvm/gen/swizzle4.hpp
+++ b/boost/qvm/gen/swizzle4.hpp
@@ -1,10 +1,10 @@
-//Copyright (c) 2008-2016 Emil Dotchevski and Reverge Studios, Inc.
+//Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc.
//Distributed under the 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_QVM_D49FD4A4597E35CF3222F4CCCFD3902D
-#define BOOST_QVM_D49FD4A4597E35CF3222F4CCCFD3902D
+#ifndef BOOST_QVM_F445D3D828CEBF5C560593D97278A59
+#define BOOST_QVM_F445D3D828CEBF5C560593D97278A59
//This file was generated by a program. Do not edit manually.
diff --git a/boost/qvm/gen/vec_assign2.hpp b/boost/qvm/gen/vec_assign2.hpp
new file mode 100644
index 0000000000..2265602b7a
--- /dev/null
+++ b/boost/qvm/gen/vec_assign2.hpp
@@ -0,0 +1,56 @@
+//Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc.
+
+//Distributed under the 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_QVM_61CDD11E9D9C167272E61DF0844F4A77
+#define BOOST_QVM_61CDD11E9D9C167272E61DF0844F4A77
+
+//This file was generated by a program. Do not edit manually.
+
+#include <boost/qvm/enable_if.hpp>
+#include <boost/qvm/inline.hpp>
+#include <boost/qvm/vec_traits.hpp>
+
+namespace
+boost
+ {
+ namespace
+ qvm
+ {
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename enable_if_c<
+ vec_traits<A>::dim==2 && vec_traits<B>::dim==2,
+ A &>::type
+ assign( A & a, B const & b )
+ {
+ vec_traits<A>::template write_element<0>(a)=vec_traits<B>::template read_element<0>(b);
+ vec_traits<A>::template write_element<1>(a)=vec_traits<B>::template read_element<1>(b);
+ return a;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::assign;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int D>
+ struct assign_vv_defined;
+
+ template <>
+ struct
+ assign_vv_defined<2>
+ {
+ static bool const value=true;
+ };
+ }
+
+ }
+ }
+
+#endif
diff --git a/boost/qvm/gen/vec_assign3.hpp b/boost/qvm/gen/vec_assign3.hpp
new file mode 100644
index 0000000000..17da3ad9af
--- /dev/null
+++ b/boost/qvm/gen/vec_assign3.hpp
@@ -0,0 +1,57 @@
+//Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc.
+
+//Distributed under the 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_QVM_2D7E8392C53CBC9121E33749ECF4D5
+#define BOOST_QVM_2D7E8392C53CBC9121E33749ECF4D5
+
+//This file was generated by a program. Do not edit manually.
+
+#include <boost/qvm/enable_if.hpp>
+#include <boost/qvm/inline.hpp>
+#include <boost/qvm/vec_traits.hpp>
+
+namespace
+boost
+ {
+ namespace
+ qvm
+ {
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename enable_if_c<
+ vec_traits<A>::dim==3 && vec_traits<B>::dim==3,
+ A &>::type
+ assign( A & a, B const & b )
+ {
+ vec_traits<A>::template write_element<0>(a)=vec_traits<B>::template read_element<0>(b);
+ vec_traits<A>::template write_element<1>(a)=vec_traits<B>::template read_element<1>(b);
+ vec_traits<A>::template write_element<2>(a)=vec_traits<B>::template read_element<2>(b);
+ return a;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::assign;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int D>
+ struct assign_vv_defined;
+
+ template <>
+ struct
+ assign_vv_defined<3>
+ {
+ static bool const value=true;
+ };
+ }
+
+ }
+ }
+
+#endif
diff --git a/boost/qvm/gen/vec_assign4.hpp b/boost/qvm/gen/vec_assign4.hpp
new file mode 100644
index 0000000000..7fa7a566ef
--- /dev/null
+++ b/boost/qvm/gen/vec_assign4.hpp
@@ -0,0 +1,58 @@
+//Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc.
+
+//Distributed under the 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_QVM_D49FD4A4597E35CF3222F4CCCFD3902D
+#define BOOST_QVM_D49FD4A4597E35CF3222F4CCCFD3902D
+
+//This file was generated by a program. Do not edit manually.
+
+#include <boost/qvm/enable_if.hpp>
+#include <boost/qvm/inline.hpp>
+#include <boost/qvm/vec_traits.hpp>
+
+namespace
+boost
+ {
+ namespace
+ qvm
+ {
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename enable_if_c<
+ vec_traits<A>::dim==4 && vec_traits<B>::dim==4,
+ A &>::type
+ assign( A & a, B const & b )
+ {
+ vec_traits<A>::template write_element<0>(a)=vec_traits<B>::template read_element<0>(b);
+ vec_traits<A>::template write_element<1>(a)=vec_traits<B>::template read_element<1>(b);
+ vec_traits<A>::template write_element<2>(a)=vec_traits<B>::template read_element<2>(b);
+ vec_traits<A>::template write_element<3>(a)=vec_traits<B>::template read_element<3>(b);
+ return a;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::assign;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int D>
+ struct assign_vv_defined;
+
+ template <>
+ struct
+ assign_vv_defined<4>
+ {
+ static bool const value=true;
+ };
+ }
+
+ }
+ }
+
+#endif
diff --git a/boost/qvm/gen/vec_mat_operations2.hpp b/boost/qvm/gen/vec_mat_operations2.hpp
index d446e9b27a..8b52bd25e4 100644
--- a/boost/qvm/gen/vec_mat_operations2.hpp
+++ b/boost/qvm/gen/vec_mat_operations2.hpp
@@ -1,10 +1,10 @@
-//Copyright (c) 2008-2016 Emil Dotchevski and Reverge Studios, Inc.
+//Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc.
//Distributed under the 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_QVM_F622919DE18B1FDAB0CA992B9729D49
-#define BOOST_QVM_F622919DE18B1FDAB0CA992B9729D49
+#ifndef BOOST_QVM_48D38F75E6D91D2AE5C0F72B78818744
+#define BOOST_QVM_48D38F75E6D91D2AE5C0F72B78818744
//This file was generated by a program. Do not edit manually.
@@ -12,6 +12,7 @@
#include <boost/qvm/enable_if.hpp>
#include <boost/qvm/inline.hpp>
#include <boost/qvm/mat_traits.hpp>
+#include <boost/qvm/vec_traits.hpp>
namespace
boost
diff --git a/boost/qvm/gen/vec_mat_operations3.hpp b/boost/qvm/gen/vec_mat_operations3.hpp
index deec8ec04e..9e0da9045e 100644
--- a/boost/qvm/gen/vec_mat_operations3.hpp
+++ b/boost/qvm/gen/vec_mat_operations3.hpp
@@ -1,10 +1,10 @@
-//Copyright (c) 2008-2016 Emil Dotchevski and Reverge Studios, Inc.
+//Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc.
//Distributed under the 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_QVM_2C807EC599D5E980B2EAC9CC53BF67D6
-#define BOOST_QVM_2C807EC599D5E980B2EAC9CC53BF67D6
+#ifndef BOOST_QVM_E5F500D4618DBE7B51573B33821F
+#define BOOST_QVM_E5F500D4618DBE7B51573B33821F
//This file was generated by a program. Do not edit manually.
@@ -12,6 +12,7 @@
#include <boost/qvm/enable_if.hpp>
#include <boost/qvm/inline.hpp>
#include <boost/qvm/mat_traits.hpp>
+#include <boost/qvm/vec_traits.hpp>
namespace
boost
diff --git a/boost/qvm/gen/vec_mat_operations4.hpp b/boost/qvm/gen/vec_mat_operations4.hpp
index 3016cf2465..ab7db98e31 100644
--- a/boost/qvm/gen/vec_mat_operations4.hpp
+++ b/boost/qvm/gen/vec_mat_operations4.hpp
@@ -1,10 +1,10 @@
-//Copyright (c) 2008-2016 Emil Dotchevski and Reverge Studios, Inc.
+//Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc.
//Distributed under the 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_QVM_BF14D67E2DDC8E6683EF574961FF698F
-#define BOOST_QVM_BF14D67E2DDC8E6683EF574961FF698F
+#ifndef BOOST_QVM_187092DA6454CEB1853E6915F8466A4
+#define BOOST_QVM_187092DA6454CEB1853E6915F8466A4
//This file was generated by a program. Do not edit manually.
@@ -12,6 +12,7 @@
#include <boost/qvm/enable_if.hpp>
#include <boost/qvm/inline.hpp>
#include <boost/qvm/mat_traits.hpp>
+#include <boost/qvm/vec_traits.hpp>
namespace
boost
diff --git a/boost/qvm/gen/vec_operations2.hpp b/boost/qvm/gen/vec_operations2.hpp
index 00ee6d6eb5..08faeddb38 100644
--- a/boost/qvm/gen/vec_operations2.hpp
+++ b/boost/qvm/gen/vec_operations2.hpp
@@ -1,22 +1,20 @@
-//Copyright (c) 2008-2016 Emil Dotchevski and Reverge Studios, Inc.
+//Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc.
//Distributed under the 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_QVM_5DD4CBFC96F5453B13D89A1CDBAE32
-#define BOOST_QVM_5DD4CBFC96F5453B13D89A1CDBAE32
+#ifndef BOOST_QVM_F622919DE18B1FDAB0CA992B9729D49
+#define BOOST_QVM_F622919DE18B1FDAB0CA992B9729D49
//This file was generated by a program. Do not edit manually.
#include <boost/qvm/deduce_scalar.hpp>
#include <boost/qvm/deduce_vec.hpp>
-#include <boost/qvm/enable_if.hpp>
#include <boost/qvm/error.hpp>
-#include <boost/qvm/inline.hpp>
+#include <boost/qvm/gen/vec_assign2.hpp>
#include <boost/qvm/math.hpp>
#include <boost/qvm/static_assert.hpp>
#include <boost/qvm/throw_exception.hpp>
-#include <boost/qvm/vec_traits.hpp>
namespace
boost
@@ -324,38 +322,6 @@ boost
};
}
- template <class A,class B>
- BOOST_QVM_INLINE_OPERATIONS
- typename enable_if_c<
- vec_traits<A>::dim==2 && vec_traits<B>::dim==2,
- A &>::type
- assign( A & a, B const & b )
- {
- vec_traits<A>::template write_element<0>(a)=vec_traits<B>::template read_element<0>(b);
- vec_traits<A>::template write_element<1>(a)=vec_traits<B>::template read_element<1>(b);
- return a;
- }
-
- namespace
- sfinae
- {
- using ::boost::qvm::assign;
- }
-
- namespace
- qvm_detail
- {
- template <int D>
- struct assign_vv_defined;
-
- template <>
- struct
- assign_vv_defined<2>
- {
- static bool const value=true;
- };
- }
-
template <class R,class A>
BOOST_QVM_INLINE_OPERATIONS
typename enable_if_c<
diff --git a/boost/qvm/gen/vec_operations3.hpp b/boost/qvm/gen/vec_operations3.hpp
index d894066efc..c985721d65 100644
--- a/boost/qvm/gen/vec_operations3.hpp
+++ b/boost/qvm/gen/vec_operations3.hpp
@@ -1,22 +1,20 @@
-//Copyright (c) 2008-2016 Emil Dotchevski and Reverge Studios, Inc.
+//Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc.
//Distributed under the 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_QVM_209A50EE407836FD124932F69E7D49DC
-#define BOOST_QVM_209A50EE407836FD124932F69E7D49DC
+#ifndef BOOST_QVM_2C807EC599D5E980B2EAC9CC53BF67D6
+#define BOOST_QVM_2C807EC599D5E980B2EAC9CC53BF67D6
//This file was generated by a program. Do not edit manually.
#include <boost/qvm/deduce_scalar.hpp>
#include <boost/qvm/deduce_vec.hpp>
-#include <boost/qvm/enable_if.hpp>
#include <boost/qvm/error.hpp>
-#include <boost/qvm/inline.hpp>
+#include <boost/qvm/gen/vec_assign3.hpp>
#include <boost/qvm/math.hpp>
#include <boost/qvm/static_assert.hpp>
#include <boost/qvm/throw_exception.hpp>
-#include <boost/qvm/vec_traits.hpp>
namespace
boost
@@ -333,39 +331,6 @@ boost
};
}
- template <class A,class B>
- BOOST_QVM_INLINE_OPERATIONS
- typename enable_if_c<
- vec_traits<A>::dim==3 && vec_traits<B>::dim==3,
- A &>::type
- assign( A & a, B const & b )
- {
- vec_traits<A>::template write_element<0>(a)=vec_traits<B>::template read_element<0>(b);
- vec_traits<A>::template write_element<1>(a)=vec_traits<B>::template read_element<1>(b);
- vec_traits<A>::template write_element<2>(a)=vec_traits<B>::template read_element<2>(b);
- return a;
- }
-
- namespace
- sfinae
- {
- using ::boost::qvm::assign;
- }
-
- namespace
- qvm_detail
- {
- template <int D>
- struct assign_vv_defined;
-
- template <>
- struct
- assign_vv_defined<3>
- {
- static bool const value=true;
- };
- }
-
template <class R,class A>
BOOST_QVM_INLINE_OPERATIONS
typename enable_if_c<
diff --git a/boost/qvm/gen/vec_operations4.hpp b/boost/qvm/gen/vec_operations4.hpp
index 91049445a9..e3edfa27c3 100644
--- a/boost/qvm/gen/vec_operations4.hpp
+++ b/boost/qvm/gen/vec_operations4.hpp
@@ -1,22 +1,20 @@
-//Copyright (c) 2008-2016 Emil Dotchevski and Reverge Studios, Inc.
+//Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc.
//Distributed under the 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_QVM_AD4F14F2444066D06BC430B7323BA122
-#define BOOST_QVM_AD4F14F2444066D06BC430B7323BA122
+#ifndef BOOST_QVM_BF14D67E2DDC8E6683EF574961FF698F
+#define BOOST_QVM_BF14D67E2DDC8E6683EF574961FF698F
//This file was generated by a program. Do not edit manually.
#include <boost/qvm/deduce_scalar.hpp>
#include <boost/qvm/deduce_vec.hpp>
-#include <boost/qvm/enable_if.hpp>
#include <boost/qvm/error.hpp>
-#include <boost/qvm/inline.hpp>
+#include <boost/qvm/gen/vec_assign4.hpp>
#include <boost/qvm/math.hpp>
#include <boost/qvm/static_assert.hpp>
#include <boost/qvm/throw_exception.hpp>
-#include <boost/qvm/vec_traits.hpp>
namespace
boost
@@ -342,40 +340,6 @@ boost
};
}
- template <class A,class B>
- BOOST_QVM_INLINE_OPERATIONS
- typename enable_if_c<
- vec_traits<A>::dim==4 && vec_traits<B>::dim==4,
- A &>::type
- assign( A & a, B const & b )
- {
- vec_traits<A>::template write_element<0>(a)=vec_traits<B>::template read_element<0>(b);
- vec_traits<A>::template write_element<1>(a)=vec_traits<B>::template read_element<1>(b);
- vec_traits<A>::template write_element<2>(a)=vec_traits<B>::template read_element<2>(b);
- vec_traits<A>::template write_element<3>(a)=vec_traits<B>::template read_element<3>(b);
- return a;
- }
-
- namespace
- sfinae
- {
- using ::boost::qvm::assign;
- }
-
- namespace
- qvm_detail
- {
- template <int D>
- struct assign_vv_defined;
-
- template <>
- struct
- assign_vv_defined<4>
- {
- static bool const value=true;
- };
- }
-
template <class R,class A>
BOOST_QVM_INLINE_OPERATIONS
typename enable_if_c<
diff --git a/boost/qvm/mat.hpp b/boost/qvm/mat.hpp
index cd17d41626..a3d44a9699 100644
--- a/boost/qvm/mat.hpp
+++ b/boost/qvm/mat.hpp
@@ -6,7 +6,7 @@
#ifndef UUID_67E67D68A32F11DEA56FD18556D89593
#define UUID_67E67D68A32F11DEA56FD18556D89593
-#include <boost/qvm/inline.hpp>
+#include <boost/qvm/detail/mat_assign.hpp>
#include <boost/qvm/assert.hpp>
#include <boost/qvm/static_assert.hpp>
diff --git a/boost/qvm/mat_operations.hpp b/boost/qvm/mat_operations.hpp
index 0ec221ccff..ccd3612922 100644
--- a/boost/qvm/mat_operations.hpp
+++ b/boost/qvm/mat_operations.hpp
@@ -6,6 +6,7 @@
#ifndef UUID_4F915D9ED30A11DF962186E3DFD72085
#define UUID_4F915D9ED30A11DF962186E3DFD72085
+#include <boost/qvm/detail/mat_assign.hpp>
#include <boost/qvm/mat_operations2.hpp>
#include <boost/qvm/mat_operations3.hpp>
#include <boost/qvm/mat_operations4.hpp>
@@ -102,62 +103,6 @@ boost
////////////////////////////////////////////////
- namespace
- qvm_detail
- {
- template <int M,int N>
- struct
- assign_mm_defined
- {
- static bool const value=false;
- };
-
- template <int I,int N>
- struct
- copy_matrix_elements
- {
- template <class A,class B>
- static
- BOOST_QVM_INLINE_CRITICAL
- void
- f( A & a, B const & b )
- {
- mat_traits<A>::template write_element<I/mat_traits<A>::cols,I%mat_traits<A>::cols>(a) =
- mat_traits<B>::template read_element<I/mat_traits<B>::cols,I%mat_traits<B>::cols>(b);
- copy_matrix_elements<I+1,N>::f(a,b);
- }
- };
-
- template <int N>
- struct
- copy_matrix_elements<N,N>
- {
- template <class A,class B>
- static
- BOOST_QVM_INLINE_CRITICAL
- void
- f( A &, B const & )
- {
- }
- };
- }
-
- template <class A,class B>
- BOOST_QVM_INLINE_TRIVIAL
- typename boost::enable_if_c<
- is_mat<A>::value && is_mat<B>::value &&
- mat_traits<A>::rows==mat_traits<B>::rows &&
- mat_traits<A>::cols==mat_traits<B>::cols &&
- !qvm_detail::assign_mm_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
- A &>::type
- assign( A & a, B const & b )
- {
- qvm_detail::copy_matrix_elements<0,mat_traits<A>::rows*mat_traits<A>::cols>::f(a,b);
- return a;
- }
-
- ////////////////////////////////////////////////
-
template <class A,class B,class Cmp>
BOOST_QVM_INLINE_OPERATIONS
typename enable_if_c<
diff --git a/boost/qvm/quat.hpp b/boost/qvm/quat.hpp
index 1fcdd8046b..cd078ee091 100644
--- a/boost/qvm/quat.hpp
+++ b/boost/qvm/quat.hpp
@@ -6,7 +6,7 @@
#ifndef UUID_49C5A1042AEF11DF9603880056D89593
#define UUID_49C5A1042AEF11DF9603880056D89593
-#include <boost/qvm/inline.hpp>
+#include <boost/qvm/detail/quat_assign.hpp>
#include <boost/qvm/assert.hpp>
#include <boost/qvm/static_assert.hpp>
diff --git a/boost/qvm/quat_operations.hpp b/boost/qvm/quat_operations.hpp
index 94195ad051..aad0331fc6 100644
--- a/boost/qvm/quat_operations.hpp
+++ b/boost/qvm/quat_operations.hpp
@@ -6,8 +6,7 @@
#ifndef UUID_E6519754D19211DFB8405F74DFD72085
#define UUID_E6519754D19211DFB8405F74DFD72085
-#include <boost/qvm/inline.hpp>
-#include <boost/qvm/enable_if.hpp>
+#include <boost/qvm/detail/quat_assign.hpp>
#include <boost/qvm/deduce_quat.hpp>
#include <boost/qvm/mat_traits.hpp>
#include <boost/qvm/scalar_traits.hpp>
@@ -72,20 +71,6 @@ boost
////////////////////////////////////////////////
- template <class A,class B>
- BOOST_QVM_INLINE_OPERATIONS
- typename enable_if_c<
- is_quat<A>::value && is_quat<B>::value,
- A &>::type
- assign( A & a, B const & b )
- {
- quat_traits<A>::template write_element<0>(a) = quat_traits<B>::template read_element<0>(b);
- quat_traits<A>::template write_element<1>(a) = quat_traits<B>::template read_element<1>(b);
- quat_traits<A>::template write_element<2>(a) = quat_traits<B>::template read_element<2>(b);
- quat_traits<A>::template write_element<3>(a) = quat_traits<B>::template read_element<3>(b);
- return a;
- }
-
template <class A,class B,class Cmp>
BOOST_QVM_INLINE_OPERATIONS
typename enable_if_c<
diff --git a/boost/qvm/vec.hpp b/boost/qvm/vec.hpp
index a14958a9a0..950e58f429 100644
--- a/boost/qvm/vec.hpp
+++ b/boost/qvm/vec.hpp
@@ -6,7 +6,7 @@
#ifndef UUID_44EB56F0A33711DEB31B41BB56D89593
#define UUID_44EB56F0A33711DEB31B41BB56D89593
-#include <boost/qvm/inline.hpp>
+#include <boost/qvm/detail/vec_assign.hpp>
#include <boost/qvm/assert.hpp>
#include <boost/qvm/static_assert.hpp>
diff --git a/boost/qvm/vec_operations.hpp b/boost/qvm/vec_operations.hpp
index 5d42df9842..075e03fba9 100644
--- a/boost/qvm/vec_operations.hpp
+++ b/boost/qvm/vec_operations.hpp
@@ -6,6 +6,7 @@
#ifndef UUID_384AFF3AD23A11DFA80B754FE0D72085
#define UUID_384AFF3AD23A11DFA80B754FE0D72085
+#include <boost/qvm/detail/vec_assign.hpp>
#include <boost/qvm/vec_operations2.hpp>
#include <boost/qvm/vec_operations3.hpp>
#include <boost/qvm/vec_operations4.hpp>
@@ -97,58 +98,6 @@ boost
{
template <int D>
struct
- assign_vv_defined
- {
- static bool const value=false;
- };
-
- template <int I,int N>
- struct
- copy_vector_elements
- {
- template <class A,class B>
- static
- void
- f( A & a, B const & b )
- {
- vec_traits<A>::template write_element<I>(a)=vec_traits<B>::template read_element<I>(b);
- copy_vector_elements<I+1,N>::f(a,b);
- }
- };
-
- template <int N>
- struct
- copy_vector_elements<N,N>
- {
- template <class A,class B>
- static
- void
- f( A &, B const & )
- {
- }
- };
- }
-
- template <class A,class B>
- inline
- typename boost::enable_if_c<
- is_vec<A>::value && is_vec<B>::value &&
- vec_traits<A>::dim==vec_traits<B>::dim &&
- !qvm_detail::assign_vv_defined<vec_traits<A>::dim>::value,
- A &>::type
- assign( A & a, B const & b )
- {
- qvm_detail::copy_vector_elements<0,vec_traits<A>::dim>::f(a,b);
- return a;
- }
-
- ////////////////////////////////////////////////
-
- namespace
- qvm_detail
- {
- template <int D>
- struct
convert_to_v_defined
{
static bool const value=false;
diff --git a/boost/scoped_array.hpp b/boost/scoped_array.hpp
index c02fa316bc..d91889b7cf 100644
--- a/boost/scoped_array.hpp
+++ b/boost/scoped_array.hpp
@@ -8,8 +8,7 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
-// http://www.boost.org/libs/smart_ptr/scoped_array.htm
-//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
#include <boost/smart_ptr/scoped_array.hpp>
diff --git a/boost/scoped_ptr.hpp b/boost/scoped_ptr.hpp
index cb916dac1d..334a22e2fe 100644
--- a/boost/scoped_ptr.hpp
+++ b/boost/scoped_ptr.hpp
@@ -8,8 +8,7 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
-// http://www.boost.org/libs/smart_ptr/scoped_ptr.htm
-//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
#include <boost/smart_ptr/scoped_ptr.hpp>
diff --git a/boost/serialization/array.hpp b/boost/serialization/array.hpp
index 61708b3075..612d1a6198 100644
--- a/boost/serialization/array.hpp
+++ b/boost/serialization/array.hpp
@@ -23,6 +23,8 @@ namespace std{
} // namespace std
#endif
+#include <boost/serialization/array_wrapper.hpp>
+
#ifndef BOOST_NO_CXX11_HDR_ARRAY
#include <array>
diff --git a/boost/serialization/binary_object.hpp b/boost/serialization/binary_object.hpp
index 23c734be3d..5c9038e5a9 100644
--- a/boost/serialization/binary_object.hpp
+++ b/boost/serialization/binary_object.hpp
@@ -55,7 +55,7 @@ struct binary_object :
m_size = rhs.m_size;
return *this;
}
- binary_object(/* const */ void * const t, std::size_t size) :
+ binary_object(const void * const t, std::size_t size) :
m_t(t),
m_size(size)
{}
@@ -69,7 +69,7 @@ struct binary_object :
// wrappers follow the naming convention make_xxxxx
inline
const binary_object
-make_binary_object(/* const */ void * t, std::size_t size){
+make_binary_object(const void * t, std::size_t size){
return binary_object(t, size);
}
diff --git a/boost/serialization/collections_load_imp.hpp b/boost/serialization/collections_load_imp.hpp
index c3b165a837..e042c0c130 100644
--- a/boost/serialization/collections_load_imp.hpp
+++ b/boost/serialization/collections_load_imp.hpp
@@ -64,7 +64,7 @@ collection_load_impl(
Archive & ar,
T & t,
collection_size_type count,
- item_version_type
+ item_version_type /*item_version*/
){
t.resize(count);
typename T::iterator hint;
diff --git a/boost/serialization/detail/is_default_constructible.hpp b/boost/serialization/detail/is_default_constructible.hpp
index 451cca4d6f..4d20b13bf3 100644
--- a/boost/serialization/detail/is_default_constructible.hpp
+++ b/boost/serialization/detail/is_default_constructible.hpp
@@ -18,31 +18,37 @@
#include <boost/config.hpp>
-#if defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 1101) \
-|| ! defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
+#if ! defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
#include <type_traits>
namespace boost{
namespace serialization {
namespace detail {
template<typename T>
- struct is_default_constructible : std::is_default_constructible<T> {};
+ struct is_default_constructible : public std::is_default_constructible<T> {};
} // detail
} // serializaition
} // boost
#else
+ // we don't have standard library support for is_default_constructible
+ // so we fake it by using boost::has_trivial_construtor. But this is not
+ // actually correct because it's possible that a default constructor
+ // to be non trivial. So when using this, make sure you're not using your
+ // own definition of of T() but are using the actual default one!
#include <boost/type_traits/has_trivial_constructor.hpp>
namespace boost{
namespace serialization {
namespace detail {
template<typename T>
- struct is_default_constructible : boost::has_trivial_constructor<T> {};
+ struct is_default_constructible : public boost::has_trivial_constructor<T> {};
} // detail
} // serializaition
} // boost
+
#endif
+
#endif // BOOST_SERIALIZATION_DETAIL_IS_DEFAULT_CONSTRUCTIBLE_HPP
diff --git a/boost/serialization/factory.hpp b/boost/serialization/factory.hpp
index db5b1a9226..2db7e7e36c 100644
--- a/boost/serialization/factory.hpp
+++ b/boost/serialization/factory.hpp
@@ -48,32 +48,33 @@ namespace boost { \
namespace serialization { \
template<> \
T * factory<T, N>(std::va_list ap){ \
- BOOST_PP_IF(BOOST_PP_GREATER(N,0) \
- ,A0 a0 = va_arg(ap, A0); \
- ,BOOST_PP_IF(BOOST_PP_GREATER(N,1) \
- ,A1 a1 = va_arg(ap, A1); \
- ,BOOST_PP_IF(BOOST_PP_GREATER(N,2) \
- ,A2 a2 = va_arg(ap, A2); \
- ,BOOST_PP_IF(BOOST_PP_GREATER(N,3) \
- ,A3 a3 = va_arg(ap, A3); \
- ,BOOST_PP_EMPTY() \
- )))) \
+ BOOST_PP_IF(BOOST_PP_GREATER(N, 0) \
+ , A0 a0 = va_arg(ap, A0);, BOOST_PP_EMPTY()) \
+ BOOST_PP_IF(BOOST_PP_GREATER(N, 1) \
+ , A1 a1 = va_arg(ap, A1);, BOOST_PP_EMPTY()) \
+ BOOST_PP_IF(BOOST_PP_GREATER(N, 2) \
+ , A2 a2 = va_arg(ap, A2);, BOOST_PP_EMPTY()) \
+ BOOST_PP_IF(BOOST_PP_GREATER(N, 3) \
+ , A3 a3 = va_arg(ap, A3);, BOOST_PP_EMPTY()) \
return new T( \
- BOOST_PP_IF(BOOST_PP_GREATER(N,0) \
- ,a0 \
- ,BOOST_PP_IF(BOOST_PP_GREATER(N,1) \
- ,a1 \
- ,BOOST_PP_IF(BOOST_PP_GREATER(N,2) \
- ,a2 \
- ,BOOST_PP_IF(BOOST_PP_GREATER(N,3) \
- ,a3 \
- ,BOOST_PP_EMPTY() \
- )))) \
+ BOOST_PP_IF(BOOST_PP_GREATER(N, 0) \
+ , a0, BOOST_PP_EMPTY()) \
+ BOOST_PP_IF(BOOST_PP_GREATER(N, 1)) \
+ , BOOST_PP_COMMA, BOOST_PP_EMPTY)() \
+ BOOST_PP_IF(BOOST_PP_GREATER(N, 1) \
+ , a1, BOOST_PP_EMPTY()) \
+ BOOST_PP_IF(BOOST_PP_GREATER(N, 2)) \
+ , BOOST_PP_COMMA, BOOST_PP_EMPTY)() \
+ BOOST_PP_IF(BOOST_PP_GREATER(N, 2) \
+ , a2, BOOST_PP_EMPTY()) \
+ BOOST_PP_IF(BOOST_PP_GREATER(N, 3)) \
+ , BOOST_PP_COMMA, BOOST_PP_EMPTY)() \
+ BOOST_PP_IF(BOOST_PP_GREATER(N, 3) \
+ , a3, BOOST_PP_EMPTY()) \
); \
} \
} \
-} \
-/**/
+} /**/
#define BOOST_SERIALIZATION_FACTORY_4(T, A0, A1, A2, A3) \
BOOST_SERIALIZATION_FACTORY(4, T, A0, A1, A2, A3)
diff --git a/boost/serialization/optional.hpp b/boost/serialization/optional.hpp
index ecd1756d50..d6ff830a8c 100644
--- a/boost/serialization/optional.hpp
+++ b/boost/serialization/optional.hpp
@@ -29,6 +29,7 @@
#include <boost/type_traits/is_pointer.hpp>
#include <boost/serialization/detail/stack_constructor.hpp>
#include <boost/serialization/detail/is_default_constructible.hpp>
+#include <boost/serialization/force_include.hpp>
// function specializations must be defined in the appropriate
// namespace - boost::serialization
@@ -46,24 +47,15 @@ void save(
// default constructor. It's possible that this could change sometime
// in the future, but for now, one will have to work around it. This can
// be done by serialization the optional<T> as optional<T *>
- BOOST_STATIC_ASSERT(
- boost::serialization::detail::is_default_constructible<T>::value
- || boost::is_pointer<T>::value
- );
+ #if ! defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
+ BOOST_STATIC_ASSERT(
+ boost::serialization::detail::is_default_constructible<T>::value
+ || boost::is_pointer<T>::value
+ );
+ #endif
const bool tflag = t.is_initialized();
ar << boost::serialization::make_nvp("initialized", tflag);
if (tflag){
- const boost::serialization::item_version_type item_version(version< T >::value);
- #if 0
- const boost::archive::library_version_type library_version(
- ar.get_library_version()
- };
- if(boost::archive::library_version_type(3) < library_version){
- ar << BOOST_SERIALIZATION_NVP(item_version);
- }
- #else
- ar << BOOST_SERIALIZATION_NVP(item_version);
- #endif
ar << boost::serialization::make_nvp("value", *t);
}
}
@@ -72,7 +64,7 @@ template<class Archive, class T>
void load(
Archive & ar,
boost::optional< T > & t,
- const unsigned int /*version*/
+ const unsigned int version
){
bool tflag;
ar >> boost::serialization::make_nvp("initialized", tflag);
@@ -81,20 +73,18 @@ void load(
return;
}
- boost::serialization::item_version_type item_version(0);
- boost::archive::library_version_type library_version(
- ar.get_library_version()
- );
- if(boost::archive::library_version_type(3) < library_version){
- ar >> BOOST_SERIALIZATION_NVP(item_version);
+ if(0 == version){
+ boost::serialization::item_version_type item_version(0);
+ boost::archive::library_version_type library_version(
+ ar.get_library_version()
+ );
+ if(boost::archive::library_version_type(3) < library_version){
+ ar >> BOOST_SERIALIZATION_NVP(item_version);
+ }
}
- detail::stack_allocate<T> tp;
- ar >> boost::serialization::make_nvp("value", tp.reference());
- t.reset(boost::move(tp.reference()));
- ar.reset_object_address(
- t.get_ptr(),
- & tp.reference()
- );
+ if(! t.is_initialized())
+ t = T();
+ ar >> boost::serialization::make_nvp("value", *t);
}
template<class Archive, class T>
@@ -106,7 +96,12 @@ void serialize(
boost::serialization::split_free(ar, t, version);
}
+template<class T>
+struct version<boost::optional<T> > {
+ BOOST_STATIC_CONSTANT(int, value = 1);
+};
+
} // serialization
-} // namespace boost
+} // boost
#endif // BOOST_SERIALIZATION_OPTIONAL_HPP_
diff --git a/boost/serialization/singleton.hpp b/boost/serialization/singleton.hpp
index a40488c6df..b50afedbb9 100644
--- a/boost/serialization/singleton.hpp
+++ b/boost/serialization/singleton.hpp
@@ -81,65 +81,57 @@ namespace serialization {
// attempt to retieve a mutable instances while locked will
// generate a assertion if compiled for debug.
+// note usage of BOOST_DLLEXPORT. These functions are in danger of
+// being eliminated by the optimizer when building an application in
+// release mode. Usage of the macro is meant to signal the compiler/linker
+// to avoid dropping these functions which seem to be unreferenced.
+// This usage is not related to autolinking.
+
class BOOST_SYMBOL_VISIBLE singleton_module :
public boost::noncopyable
{
private:
- BOOST_SERIALIZATION_DECL static bool & get_lock();
+ BOOST_SERIALIZATION_DECL BOOST_DLLEXPORT static bool & get_lock() BOOST_USED;
public:
- static void lock(){
+ BOOST_DLLEXPORT static void lock(){
get_lock() = true;
}
-
- static void unlock(){
+ BOOST_DLLEXPORT static void unlock(){
get_lock() = false;
}
-
- static bool is_locked(){
+ BOOST_DLLEXPORT static bool is_locked(){
return get_lock();
}
};
-#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
-
-namespace detail {
-
-template<class T>
-class singleton_wrapper : public T
-{
-public:
- static bool m_is_destroyed;
- ~singleton_wrapper(){
- m_is_destroyed = true;
- }
-};
-
-template<class T>
-bool detail::singleton_wrapper< T >::m_is_destroyed = false;
-
-} // detail
-
-// note usage of BOOST_DLLEXPORT. These functions are in danger of
-// being eliminated by the optimizer when building an application in
-// release mode. Usage of the macro is meant to signal the compiler/linker
-// to avoid dropping these functions which seem to be unreferenced.
-// This usage is not related to autolinking.
-
template <class T>
class singleton : public singleton_module
{
private:
- BOOST_DLLEXPORT static T & instance;
+ static T & m_instance;
// include this to provoke instantiation at pre-execution time
static void use(T const *) {}
- BOOST_DLLEXPORT static T & get_instance() {
- static detail::singleton_wrapper< T > t;
+ static T & get_instance() {
+ // use a wrapper so that types T with protected constructors
+ // can be used
+ class singleton_wrapper : public T {};
+ static singleton_wrapper t;
// refer to instance, causing it to be instantiated (and
// initialized at startup on working compilers)
- BOOST_ASSERT(! detail::singleton_wrapper< T >::m_is_destroyed);
- use(& instance);
+ BOOST_ASSERT(! is_destroyed());
+ // note that the following is absolutely essential.
+ // commenting out this statement will cause compilers to fail to
+ // construct the instance at pre-execution time. This would prevent
+ // our usage/implementation of "locking" and introduce uncertainty into
+ // the sequence of object initializaition.
+ use(& m_instance);
return static_cast<T &>(t);
}
+ static bool & get_is_destroyed(){
+ static bool is_destroyed;
+ return is_destroyed;
+ }
+
public:
BOOST_DLLEXPORT static T & get_mutable_instance(){
BOOST_ASSERT(! is_locked());
@@ -149,16 +141,24 @@ public:
return get_instance();
}
BOOST_DLLEXPORT static bool is_destroyed(){
- return detail::singleton_wrapper< T >::m_is_destroyed;
+ return get_is_destroyed();
+ }
+ BOOST_DLLEXPORT singleton(){
+ get_is_destroyed() = false;
+ }
+ BOOST_DLLEXPORT ~singleton() {
+ get_is_destroyed() = true;
}
};
template<class T>
-BOOST_DLLEXPORT T & singleton< T >::instance = singleton< T >::get_instance();
+T & singleton< T >::m_instance = singleton< T >::get_instance();
} // namespace serialization
} // namespace boost
+#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
diff --git a/boost/shared_array.hpp b/boost/shared_array.hpp
index 0700ce4f5b..6804224c27 100644
--- a/boost/shared_array.hpp
+++ b/boost/shared_array.hpp
@@ -11,7 +11,7 @@
// 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/shared_array.htm for documentation.
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
//
#include <boost/smart_ptr/shared_array.hpp>
diff --git a/boost/shared_ptr.hpp b/boost/shared_ptr.hpp
index d31978c925..cb01b26588 100644
--- a/boost/shared_ptr.hpp
+++ b/boost/shared_ptr.hpp
@@ -11,7 +11,7 @@
// 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/shared_ptr.htm for documentation.
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
//
#include <boost/smart_ptr/shared_ptr.hpp>
diff --git a/boost/signals2/detail/auto_buffer.hpp b/boost/signals2/detail/auto_buffer.hpp
index 4c55a751ae..5ff8dd2c63 100644
--- a/boost/signals2/detail/auto_buffer.hpp
+++ b/boost/signals2/detail/auto_buffer.hpp
@@ -248,6 +248,14 @@ namespace detail
auto_buffer_destroy( where, boost::has_trivial_destructor<T>() );
}
+ void auto_buffer_destroy()
+ {
+ BOOST_ASSERT( is_valid() );
+ if( buffer_ ) // do we need this check? Yes, but only
+ // for N = 0u + local instances in one_sided_swap()
+ auto_buffer_destroy( boost::has_trivial_destructor<T>() );
+ }
+
void destroy_back_n( size_type n, const boost::false_type& )
{
BOOST_ASSERT( n > 0 );
@@ -301,7 +309,7 @@ namespace detail
{
pointer new_buffer = move_to_new_buffer( new_capacity,
boost::has_nothrow_copy<T>() );
- (*this).~auto_buffer();
+ auto_buffer_destroy();
buffer_ = new_buffer;
members_.capacity_ = new_capacity;
BOOST_ASSERT( size_ <= members_.capacity_ );
@@ -355,7 +363,7 @@ namespace detail
void one_sided_swap( auto_buffer& temp ) // nothrow
{
BOOST_ASSERT( !temp.is_on_stack() );
- this->~auto_buffer();
+ auto_buffer_destroy();
// @remark: must be nothrow
get_allocator() = temp.get_allocator();
members_.capacity_ = temp.members_.capacity_;
@@ -506,7 +514,7 @@ namespace detail
{
// @remark: we release memory as early as possible
// since we only give the basic guarantee
- (*this).~auto_buffer();
+ auto_buffer_destroy();
buffer_ = 0;
pointer new_buffer = allocate( r.size() );
boost::multi_index::detail::scope_guard guard =
@@ -597,10 +605,7 @@ namespace detail
~auto_buffer()
{
- BOOST_ASSERT( is_valid() );
- if( buffer_ ) // do we need this check? Yes, but only
- // for N = 0u + local instances in one_sided_swap()
- auto_buffer_destroy( boost::has_trivial_destructor<T>() );
+ auto_buffer_destroy();
}
public:
@@ -1033,7 +1038,7 @@ namespace detail
pointer new_buffer = static_cast<T*>(other->members_.address());
copy_impl( one_on_stack->begin(), one_on_stack->end(),
new_buffer ); // strong
- one_on_stack->~auto_buffer(); // nothrow
+ one_on_stack->auto_buffer_destroy(); // nothrow
boost::swap( get_allocator(), r.get_allocator() ); // assume nothrow
boost::swap( members_.capacity_, r.members_.capacity_ );
boost::swap( size_, r.size_ );
diff --git a/boost/signals2/detail/slot_call_iterator.hpp b/boost/signals2/detail/slot_call_iterator.hpp
index 9fee16ec69..769f6c222d 100644
--- a/boost/signals2/detail/slot_call_iterator.hpp
+++ b/boost/signals2/detail/slot_call_iterator.hpp
@@ -78,12 +78,12 @@ namespace boost {
: public boost::iterator_facade<slot_call_iterator_t<Function, Iterator, ConnectionBody>,
typename Function::result_type,
boost::single_pass_traversal_tag,
- typename boost::add_const<typename boost::add_reference<typename Function::result_type>::type>::type >
+ typename boost::add_reference<typename boost::add_const<typename Function::result_type>::type>::type >
{
typedef boost::iterator_facade<slot_call_iterator_t<Function, Iterator, ConnectionBody>,
typename Function::result_type,
boost::single_pass_traversal_tag,
- typename boost::add_const<typename boost::add_reference<typename Function::result_type>::type>::type >
+ typename boost::add_reference<typename boost::add_const<typename Function::result_type>::type>::type >
inherited;
typedef typename Function::result_type result_type;
diff --git a/boost/smart_ptr.hpp b/boost/smart_ptr.hpp
index b5e569d8d3..6fabfc5388 100644
--- a/boost/smart_ptr.hpp
+++ b/boost/smart_ptr.hpp
@@ -11,21 +11,16 @@
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
-// http://www.boost.org/libs/smart_ptr/smart_ptr.htm
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
//
-#include <boost/config.hpp>
-
#include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
-
-#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
-# include <boost/weak_ptr.hpp>
-# include <boost/intrusive_ptr.hpp>
-# include <boost/enable_shared_from_this.hpp>
-# include <boost/make_shared.hpp>
-#endif
+#include <boost/weak_ptr.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/make_shared.hpp>
#endif // #ifndef BOOST_SMART_PTR_HPP_INCLUDED
diff --git a/boost/smart_ptr/allocate_local_shared_array.hpp b/boost/smart_ptr/allocate_local_shared_array.hpp
new file mode 100644
index 0000000000..f46f11049b
--- /dev/null
+++ b/boost/smart_ptr/allocate_local_shared_array.hpp
@@ -0,0 +1,228 @@
+/*
+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)
+*/
+#ifndef BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP
+#define BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP
+
+#include <boost/smart_ptr/allocate_shared_array.hpp>
+#include <boost/smart_ptr/local_shared_ptr.hpp>
+
+namespace boost {
+namespace detail {
+
+template<class>
+struct lsp_if_array { };
+
+template<class T>
+struct lsp_if_array<T[]> {
+ typedef boost::local_shared_ptr<T[]> type;
+};
+
+template<class>
+struct lsp_if_size_array { };
+
+template<class T, std::size_t N>
+struct lsp_if_size_array<T[N]> {
+ typedef boost::local_shared_ptr<T[N]> type;
+};
+
+class lsp_array_base
+ : public local_counted_base {
+public:
+ void set(sp_counted_base* base) BOOST_SP_NOEXCEPT {
+ count_ = shared_count(base);
+ }
+
+ virtual void local_cb_destroy() BOOST_SP_NOEXCEPT {
+ shared_count().swap(count_);
+ }
+
+ virtual shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT {
+ return count_;
+ }
+
+private:
+ shared_count count_;
+};
+
+template<class A>
+class lsp_array_state
+ : public sp_array_state<A> {
+public:
+ template<class U>
+ lsp_array_state(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
+ : sp_array_state<A>(other, size) { }
+
+ lsp_array_base& base() BOOST_SP_NOEXCEPT {
+ return base_;
+ }
+
+private:
+ lsp_array_base base_;
+};
+
+template<class A, std::size_t N>
+class lsp_size_array_state
+ : public sp_size_array_state<A, N> {
+public:
+ template<class U>
+ lsp_size_array_state(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
+ : sp_size_array_state<A, N>(other, size) { }
+
+ lsp_array_base& base() BOOST_SP_NOEXCEPT {
+ return base_;
+ }
+
+private:
+ lsp_array_base base_;
+};
+
+} /* detail */
+
+template<class T, class A>
+inline typename detail::lsp_if_array<T>::type
+allocate_local_shared(const A& allocator, std::size_t count)
+{
+ typedef typename detail::sp_array_element<T>::type type;
+ typedef typename detail::sp_array_scalar<T>::type scalar;
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::lsp_array_state<other> state;
+ typedef detail::sp_array_base<state> base;
+ std::size_t size = count * detail::sp_array_count<type>::value;
+ detail::sp_array_result<other, base> result(allocator, size);
+ base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(allocator, size, start);
+ detail::lsp_array_base& local = node->state().base();
+ local.set(node);
+ result.release();
+ return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), &local);
+}
+
+template<class T, class A>
+inline typename detail::lsp_if_size_array<T>::type
+allocate_local_shared(const A& allocator)
+{
+ enum {
+ size = detail::sp_array_count<T>::value
+ };
+ typedef typename detail::sp_array_element<T>::type type;
+ typedef typename detail::sp_array_scalar<T>::type scalar;
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::lsp_size_array_state<other, size> state;
+ typedef detail::sp_array_base<state> base;
+ detail::sp_array_result<other, base> result(allocator, size);
+ base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(allocator, size, start);
+ detail::lsp_array_base& local = node->state().base();
+ local.set(node);
+ result.release();
+ return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), &local);
+}
+
+template<class T, class A>
+inline typename detail::lsp_if_array<T>::type
+allocate_local_shared(const A& allocator, std::size_t count,
+ const typename detail::sp_array_element<T>::type& value)
+{
+ typedef typename detail::sp_array_element<T>::type type;
+ typedef typename detail::sp_array_scalar<T>::type scalar;
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::lsp_array_state<other> state;
+ typedef detail::sp_array_base<state> base;
+ std::size_t size = count * detail::sp_array_count<type>::value;
+ detail::sp_array_result<other, base> result(allocator, size);
+ base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(allocator, size,
+ reinterpret_cast<const scalar*>(&value),
+ detail::sp_array_count<type>::value, start);
+ detail::lsp_array_base& local = node->state().base();
+ local.set(node);
+ result.release();
+ return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), &local);
+}
+
+template<class T, class A>
+inline typename detail::lsp_if_size_array<T>::type
+allocate_local_shared(const A& allocator,
+ const typename detail::sp_array_element<T>::type& value)
+{
+ enum {
+ size = detail::sp_array_count<T>::value
+ };
+ typedef typename detail::sp_array_element<T>::type type;
+ typedef typename detail::sp_array_scalar<T>::type scalar;
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::lsp_size_array_state<other, size> state;
+ typedef detail::sp_array_base<state> base;
+ detail::sp_array_result<other, base> result(allocator, size);
+ base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(allocator, size,
+ reinterpret_cast<const scalar*>(&value),
+ detail::sp_array_count<type>::value, start);
+ detail::lsp_array_base& local = node->state().base();
+ local.set(node);
+ result.release();
+ return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), &local);
+}
+
+template<class T, class A>
+inline typename detail::lsp_if_array<T>::type
+allocate_local_shared_noinit(const A& allocator, std::size_t count)
+{
+ typedef typename detail::sp_array_element<T>::type type;
+ typedef typename detail::sp_array_scalar<T>::type scalar;
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::lsp_array_state<other> state;
+ typedef detail::sp_array_base<state, false> base;
+ std::size_t size = count * detail::sp_array_count<type>::value;
+ detail::sp_array_result<other, base> result(allocator, size);
+ base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
+ size, start);
+ detail::lsp_array_base& local = node->state().base();
+ local.set(node);
+ result.release();
+ return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), &local);
+}
+
+template<class T, class A>
+inline typename detail::lsp_if_size_array<T>::type
+allocate_local_shared_noinit(const A& allocator)
+{
+ enum {
+ size = detail::sp_array_count<T>::value
+ };
+ typedef typename detail::sp_array_element<T>::type type;
+ typedef typename detail::sp_array_scalar<T>::type scalar;
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::lsp_size_array_state<other, size> state;
+ typedef detail::sp_array_base<state, false> base;
+ detail::sp_array_result<other, base> result(allocator, size);
+ base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
+ size, start);
+ detail::lsp_array_base& local = node->state().base();
+ local.set(node);
+ result.release();
+ return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), &local);
+}
+
+} /* boost */
+
+#endif
diff --git a/boost/smart_ptr/allocate_shared_array.hpp b/boost/smart_ptr/allocate_shared_array.hpp
index b43b43d575..23c35aff3f 100644
--- a/boost/smart_ptr/allocate_shared_array.hpp
+++ b/boost/smart_ptr/allocate_shared_array.hpp
@@ -9,9 +9,10 @@ Distributed under the Boost Software License, Version 1.0.
#define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/type_traits/has_trivial_assign.hpp>
#include <boost/type_traits/has_trivial_constructor.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
-#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/type_with_alignment.hpp>
namespace boost {
@@ -105,37 +106,24 @@ struct sp_array_count<T[N]> {
};
};
-template<class T>
-struct sp_array_count<T[]> { };
-
-template<class D, class T>
-inline D*
-sp_get_deleter(const
- boost::shared_ptr<T>& value) BOOST_NOEXCEPT_OR_NOTHROW
-{
- return static_cast<D*>(value._internal_get_untyped_deleter());
-}
-
-template<std::size_t N, std::size_t A>
-struct sp_array_storage {
- union type {
- char value[N];
- typename boost::type_with_alignment<A>::type other;
+template<std::size_t N, std::size_t M>
+struct sp_max_size {
+ enum {
+ value = N < M ? M : N
};
};
template<std::size_t N, std::size_t M>
-struct sp_max_size {
+struct sp_align_up {
enum {
- value = N < M ? M : N
+ value = (N + M - 1) & ~(M - 1)
};
};
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
template<class A, class T>
struct sp_bind_allocator {
- typedef typename std::allocator_traits<A>::template
- rebind_alloc<T> type;
+ typedef typename std::allocator_traits<A>::template rebind_alloc<T> type;
};
#else
template<class A, class T>
@@ -144,6 +132,13 @@ struct sp_bind_allocator {
};
#endif
+template<class T>
+BOOST_CONSTEXPR inline std::size_t
+sp_objects(std::size_t size) BOOST_SP_NOEXCEPT
+{
+ return (size + sizeof(T) - 1) / sizeof(T);
+}
+
template<bool, class = void>
struct sp_enable { };
@@ -152,873 +147,549 @@ struct sp_enable<true, T> {
typedef T type;
};
-template<class T>
-inline
-typename sp_enable<boost::has_trivial_destructor<T>::value>::type
-sp_array_destroy(T*, std::size_t) BOOST_NOEXCEPT { }
+template<bool E, class A, class T>
+inline typename sp_enable<!E && boost::has_trivial_destructor<T>::value>::type
+sp_array_destroy(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { }
-template<class T>
-inline
-typename sp_enable<!boost::has_trivial_destructor<T>::value>::type
-sp_array_destroy(T* storage, std::size_t size)
+template<bool E, class A, class T>
+inline typename sp_enable<!E &&
+ !boost::has_trivial_destructor<T>::value>::type
+sp_array_destroy(A&, T* start, std::size_t size)
{
while (size > 0) {
- storage[--size].~T();
+ start[--size].~T();
}
}
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
-template<class A, class T>
-inline void
-sp_array_destroy(A& allocator, T* storage, std::size_t size)
+template<bool E, class A, class T>
+inline typename sp_enable<E>::type
+sp_array_destroy(A& allocator, T* start, std::size_t size)
{
while (size > 0) {
- std::allocator_traits<A>::destroy(allocator, &storage[--size]);
+ std::allocator_traits<A>::destroy(allocator, start + --size);
}
}
#endif
-#if !defined(BOOST_NO_EXCEPTIONS)
-template<class T>
-inline
-typename sp_enable<boost::has_trivial_constructor<T>::value ||
- boost::has_trivial_destructor<T>::value>::type
-sp_array_construct(T* storage, std::size_t size)
+template<bool E, class A, class T>
+inline typename sp_enable<!E &&
+ boost::has_trivial_constructor<T>::value &&
+ boost::has_trivial_assign<T>::value>::type
+sp_array_construct(A&, T* start, std::size_t size)
{
for (std::size_t i = 0; i < size; ++i) {
- ::new(static_cast<void*>(storage + i)) T();
+ start[i] = T();
}
}
-template<class T>
-inline
-typename sp_enable<!boost::has_trivial_constructor<T>::value &&
- !boost::has_trivial_destructor<T>::value>::type
-sp_array_construct(T* storage, std::size_t size)
+template<bool E, class A, class T>
+inline typename sp_enable<!E &&
+ boost::has_trivial_constructor<T>::value &&
+ boost::has_trivial_assign<T>::value>::type
+sp_array_construct(A&, T* start, std::size_t size, const T* list,
+ std::size_t count)
+{
+ for (std::size_t i = 0; i < size; ++i) {
+ start[i] = list[i % count];
+ }
+}
+
+#if !defined(BOOST_NO_EXCEPTIONS)
+template<bool E, class A, class T>
+inline typename sp_enable<!E &&
+ !(boost::has_trivial_constructor<T>::value &&
+ boost::has_trivial_assign<T>::value)>::type
+sp_array_construct(A& none, T* start, std::size_t size)
{
std::size_t i = 0;
try {
for (; i < size; ++i) {
- ::new(static_cast<void*>(storage + i)) T();
+ ::new(static_cast<void*>(start + i)) T();
}
} catch (...) {
- while (i > 0) {
- storage[--i].~T();
- }
+ sp_array_destroy<E>(none, start, i);
throw;
}
}
-template<class T>
-inline void
-sp_array_construct(T* storage, std::size_t size, const T* list,
+template<bool E, class A, class T>
+inline typename sp_enable<!E &&
+ !(boost::has_trivial_constructor<T>::value &&
+ boost::has_trivial_assign<T>::value)>::type
+sp_array_construct(A& none, T* start, std::size_t size, const T* list,
std::size_t count)
{
std::size_t i = 0;
try {
for (; i < size; ++i) {
- ::new(static_cast<void*>(storage + i)) T(list[i % count]);
+ ::new(static_cast<void*>(start + i)) T(list[i % count]);
}
} catch (...) {
- while (i > 0) {
- storage[--i].~T();
- }
+ sp_array_destroy<E>(none, start, i);
throw;
}
}
#else
-template<class T>
-inline void
-sp_array_construct(T* storage, std::size_t size)
+template<bool E, class A, class T>
+inline typename sp_enable<!E &&
+ !(boost::has_trivial_constructor<T>::value &&
+ boost::has_trivial_assign<T>::value)>::type
+sp_array_construct(A&, T* start, std::size_t size)
{
for (std::size_t i = 0; i < size; ++i) {
- ::new(static_cast<void*>(storage + i)) T();
+ ::new(static_cast<void*>(start + i)) T();
}
}
-template<class T>
-inline void
-sp_array_construct(T* storage, std::size_t size, const T* list,
+template<bool E, class A, class T>
+inline typename sp_enable<!E &&
+ !(boost::has_trivial_constructor<T>::value &&
+ boost::has_trivial_assign<T>::value)>::type
+sp_array_construct(A&, T* start, std::size_t size, const T* list,
std::size_t count)
{
for (std::size_t i = 0; i < size; ++i) {
- ::new(static_cast<void*>(storage + i)) T(list[i % count]);
+ ::new(static_cast<void*>(start + i)) T(list[i % count]);
}
}
#endif
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
#if !defined(BOOST_NO_EXCEPTIONS)
-template<class A, class T>
-inline void
-sp_array_construct(A& allocator, T* storage, std::size_t size)
+template<bool E, class A, class T>
+inline typename sp_enable<E>::type
+sp_array_construct(A& allocator, T* start, std::size_t size)
{
std::size_t i = 0;
try {
for (i = 0; i < size; ++i) {
- std::allocator_traits<A>::construct(allocator, storage + i);
+ std::allocator_traits<A>::construct(allocator, start + i);
}
} catch (...) {
- sp_array_destroy(allocator, storage, i);
+ sp_array_destroy<E>(allocator, start, i);
throw;
}
}
-template<class A, class T>
-inline void
-sp_array_construct(A& allocator, T* storage, std::size_t size,
- const T* list, std::size_t count)
+template<bool E, class A, class T>
+inline typename sp_enable<E>::type
+sp_array_construct(A& allocator, T* start, std::size_t size, const T* list,
+ std::size_t count)
{
std::size_t i = 0;
try {
for (i = 0; i < size; ++i) {
- std::allocator_traits<A>::construct(allocator, storage + i,
+ std::allocator_traits<A>::construct(allocator, start + i,
list[i % count]);
}
} catch (...) {
- sp_array_destroy(allocator, storage, i);
+ sp_array_destroy<E>(allocator, start, i);
throw;
}
}
#else
-template<class A, class T>
-inline void
-sp_array_construct(A& allocator, T* storage, std::size_t size)
+template<bool E, class A, class T>
+inline typename sp_enable<E>::type
+sp_array_construct(A& allocator, T* start, std::size_t size)
{
for (std::size_t i = 0; i < size; ++i) {
- std::allocator_traits<A>::construct(allocator, storage + i);
+ std::allocator_traits<A>::construct(allocator, start + i);
}
}
-template<class A, class T>
-inline void
-sp_array_construct(A& allocator, T* storage, std::size_t size,
- const T* list, std::size_t count)
+template<bool E, class A, class T>
+inline typename sp_enable<E>::type
+sp_array_construct(A& allocator, T* start, std::size_t size, const T* list,
+ std::size_t count)
{
for (std::size_t i = 0; i < size; ++i) {
- std::allocator_traits<A>::construct(allocator, storage + i,
+ std::allocator_traits<A>::construct(allocator, start + i,
list[i % count]);
}
}
#endif
#endif
-template<class T>
-inline
-typename sp_enable<boost::has_trivial_constructor<T>::value>::type
-sp_array_default(T*, std::size_t) BOOST_NOEXCEPT { }
+template<class A, class T>
+inline typename sp_enable<boost::has_trivial_constructor<T>::value>::type
+sp_array_default(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { }
#if !defined(BOOST_NO_EXCEPTIONS)
-template<class T>
-inline
-typename sp_enable<!boost::has_trivial_constructor<T>::value &&
- boost::has_trivial_destructor<T>::value>::type
-sp_array_default(T* storage, std::size_t size)
-{
- for (std::size_t i = 0; i < size; ++i) {
- ::new(static_cast<void*>(storage + i)) T;
- }
-}
-
-template<class T>
-inline
-typename sp_enable<!boost::has_trivial_constructor<T>::value &&
- !boost::has_trivial_destructor<T>::value>::type
-sp_array_default(T* storage, std::size_t size)
+template<class A, class T>
+inline typename sp_enable<!boost::has_trivial_constructor<T>::value>::type
+sp_array_default(A& none, T* start, std::size_t size)
{
std::size_t i = 0;
try {
for (; i < size; ++i) {
- ::new(static_cast<void*>(storage + i)) T;
+ ::new(static_cast<void*>(start + i)) T;
}
} catch (...) {
- while (i > 0) {
- storage[--i].~T();
- }
+ sp_array_destroy<false>(none, start, i);
throw;
}
}
#else
-template<class T>
-inline
-typename sp_enable<!boost::has_trivial_constructor<T>::value>::type
-sp_array_default(T* storage, std::size_t size)
+template<bool E, class A, class T>
+inline typename sp_enable<!boost::has_trivial_constructor<T>::value>::type
+sp_array_default(A&, T* start, std::size_t size)
{
for (std::size_t i = 0; i < size; ++i) {
- ::new(static_cast<void*>(storage + i)) T;
+ ::new(static_cast<void*>(start + i)) T;
}
}
#endif
-template<class T, std::size_t N>
-struct sp_less_align {
- enum {
- value = (boost::alignment_of<T>::value) < N
- };
-};
-
-template<class T, std::size_t N>
-BOOST_CONSTEXPR inline
-typename sp_enable<sp_less_align<T, N>::value, std::size_t>::type
-sp_align(std::size_t size) BOOST_NOEXCEPT
-{
- return (sizeof(T) * size + N - 1) & ~(N - 1);
-}
-
-template<class T, std::size_t N>
-BOOST_CONSTEXPR inline
-typename sp_enable<!sp_less_align<T, N>::value, std::size_t>::type
-sp_align(std::size_t size) BOOST_NOEXCEPT
-{
- return sizeof(T) * size;
-}
-
-template<class T>
-BOOST_CONSTEXPR inline std::size_t
-sp_types(std::size_t size) BOOST_NOEXCEPT
-{
- return (size + sizeof(T) - 1) / sizeof(T);
-}
-
-template<class T, std::size_t N>
-class sp_size_array_deleter {
-public:
- template<class U>
- static void operator_fn(U) BOOST_NOEXCEPT { }
-
- sp_size_array_deleter() BOOST_NOEXCEPT
- : enabled_(false) { }
-
- template<class A>
- sp_size_array_deleter(const A&) BOOST_NOEXCEPT
- : enabled_(false) { }
-
- sp_size_array_deleter(const sp_size_array_deleter&) BOOST_NOEXCEPT
- : enabled_(false) { }
-
- ~sp_size_array_deleter() {
- if (enabled_) {
- sp_array_destroy(reinterpret_cast<T*>(&storage_), N);
- }
- }
-
- template<class U>
- void operator()(U) {
- if (enabled_) {
- sp_array_destroy(reinterpret_cast<T*>(&storage_), N);
- enabled_ = false;
- }
- }
-
- void* construct() {
- sp_array_construct(reinterpret_cast<T*>(&storage_), N);
- enabled_ = true;
- return &storage_;
- }
-
- void* construct(const T* list, std::size_t count) {
- sp_array_construct(reinterpret_cast<T*>(&storage_), N,
- list, count);
- enabled_ = true;
- return &storage_;
- }
-
- void* construct_default() {
- sp_array_default(reinterpret_cast<T*>(&storage_), N);
- enabled_ = true;
- return &storage_;
- }
-
-private:
- bool enabled_;
- typename sp_array_storage<sizeof(T) * N,
- boost::alignment_of<T>::value>::type storage_;
-};
-
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
-template<class T, std::size_t N, class A>
-class sp_size_array_destroyer {
+template<class A>
+class sp_array_state {
public:
- template<class U>
- static void operator_fn(U) BOOST_NOEXCEPT { }
+ typedef A type;
template<class U>
- sp_size_array_destroyer(const U& allocator) BOOST_NOEXCEPT
+ sp_array_state(const U& allocator, std::size_t size) BOOST_SP_NOEXCEPT
: allocator_(allocator),
- enabled_(false) { }
-
- sp_size_array_destroyer(const sp_size_array_destroyer& other)
- BOOST_NOEXCEPT
- : allocator_(other.allocator_),
- enabled_(false) { }
-
- ~sp_size_array_destroyer() {
- if (enabled_) {
- sp_array_destroy(allocator_,
- reinterpret_cast<T*>(&storage_), N);
- }
- }
-
- template<class U>
- void operator()(U) {
- if (enabled_) {
- sp_array_destroy(allocator_,
- reinterpret_cast<T*>(&storage_), N);
- enabled_ = false;
- }
- }
-
- void* construct() {
- sp_array_construct(allocator_,
- reinterpret_cast<T*>(&storage_), N);
- enabled_ = true;
- return &storage_;
- }
-
- void* construct(const T* list, std::size_t count) {
- sp_array_construct(allocator_,
- reinterpret_cast<T*>(&storage_), N, list, count);
- enabled_ = true;
- return &storage_;
- }
-
- const A& allocator() const BOOST_NOEXCEPT {
- return allocator_;
- }
-
-private:
- typename sp_array_storage<sizeof(T) * N,
- boost::alignment_of<T>::value>::type storage_;
- A allocator_;
- bool enabled_;
-};
-#endif
-
-template<class T>
-class sp_array_deleter {
-public:
- template<class U>
- static void operator_fn(U) BOOST_NOEXCEPT { }
-
- sp_array_deleter(std::size_t size) BOOST_NOEXCEPT
- : address_(0),
size_(size) { }
- template<class A>
- sp_array_deleter(const A& allocator) BOOST_NOEXCEPT
- : address_(0),
- size_(allocator.size()) { }
-
- template<class A>
- sp_array_deleter(const A&, std::size_t size) BOOST_NOEXCEPT
- : address_(0),
- size_(size) { }
-
- sp_array_deleter(const sp_array_deleter& other) BOOST_NOEXCEPT
- : address_(0),
- size_(other.size_) { }
-
- ~sp_array_deleter() {
- if (address_) {
- sp_array_destroy(static_cast<T*>(address_), size_);
- }
- }
-
- template<class U>
- void operator()(U) {
- if (address_) {
- sp_array_destroy(static_cast<T*>(address_), size_);
- address_ = 0;
- }
- }
-
- void construct(T* address) {
- sp_array_construct(address, size_);
- address_ = address;
- }
-
- void construct(T* address, const T* list, std::size_t count) {
- sp_array_construct(address, size_, list, count);
- address_ = address;
- }
-
- void construct_default(T* address) {
- sp_array_default(address, size_);
- address_ = address;
- }
-
- std::size_t size() const BOOST_NOEXCEPT {
- return size_;
- }
-
-private:
- void* address_;
- std::size_t size_;
-};
-
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
-template<class T, class A>
-class sp_array_destroyer {
-public:
- template<class U>
- static void operator_fn(U) BOOST_NOEXCEPT { }
-
- template<class U>
- sp_array_destroyer(const U& allocator, std::size_t size)
- BOOST_NOEXCEPT
- : allocator_(allocator),
- size_(size),
- address_(0) { }
-
- template<class U>
- sp_array_destroyer(const U& allocator) BOOST_NOEXCEPT
- : allocator_(allocator.allocator()),
- size_(allocator.size()),
- address_(0) { }
-
- sp_array_destroyer(const sp_array_destroyer& other) BOOST_NOEXCEPT
- : allocator_(other.allocator_),
- size_(other.size_),
- address_(0) { }
-
- ~sp_array_destroyer() {
- if (address_) {
- sp_array_destroy(allocator_, static_cast<T*>(address_),
- size_);
- }
- }
-
- template<class U>
- void operator()(U) {
- if (address_) {
- sp_array_destroy(allocator_, static_cast<T*>(address_),
- size_);
- address_ = 0;
- }
- }
-
- void construct(T* address) {
- sp_array_construct(allocator_, address, size_);
- address_ = address;
- }
-
- void construct(T* address, const T* list, std::size_t count) {
- sp_array_construct(allocator_, address, size_, list, count);
- address_ = address;
- }
-
- const A& allocator() const BOOST_NOEXCEPT {
+ A& allocator() BOOST_SP_NOEXCEPT {
return allocator_;
}
- std::size_t size() const BOOST_NOEXCEPT {
+ std::size_t size() const BOOST_SP_NOEXCEPT {
return size_;
}
private:
A allocator_;
std::size_t size_;
- void* address_;
};
-#endif
-
-template<class T, class A>
-class sp_array_allocator {
- template<class U, class V>
- friend class sp_array_allocator;
+template<class A, std::size_t N>
+class sp_size_array_state {
public:
- typedef typename A::value_type value_type;
-
-private:
- enum {
- alignment = sp_max_size<boost::alignment_of<T>::value,
- boost::alignment_of<value_type>::value>::value
- };
-
- typedef typename boost::type_with_alignment<alignment>::type type;
- typedef typename sp_bind_allocator<A, type>::type type_allocator;
-
-public:
- template<class U>
- struct rebind {
- typedef sp_array_allocator<T,
- typename sp_bind_allocator<A, U>::type> other;
- };
-
- sp_array_allocator(const A& allocator, std::size_t size,
- void** result) BOOST_NOEXCEPT
- : allocator_(allocator),
- size_(size),
- result_(result) { }
-
- sp_array_allocator(const A& allocator, std::size_t size)
- BOOST_NOEXCEPT
- : allocator_(allocator),
- size_(size) { }
+ typedef A type;
template<class U>
- sp_array_allocator(const sp_array_allocator<T, U>& other)
- BOOST_NOEXCEPT
- : allocator_(other.allocator_),
- size_(other.size_),
- result_(other.result_) { }
-
- value_type* allocate(std::size_t count) {
- type_allocator allocator(allocator_);
- std::size_t node = sp_align<value_type, alignment>(count);
- std::size_t size = sp_types<type>(node + sizeof(T) * size_);
- type* address = allocator.allocate(size);
- *result_ = reinterpret_cast<char*>(address) + node;
- return reinterpret_cast<value_type*>(address);
- }
+ sp_size_array_state(const U& allocator, std::size_t) BOOST_SP_NOEXCEPT
+ : allocator_(allocator) { }
- void deallocate(value_type* value, std::size_t count) {
- type_allocator allocator(allocator_);
- std::size_t node = sp_align<value_type, alignment>(count);
- std::size_t size = sp_types<type>(node + sizeof(T) * size_);
- allocator.deallocate(reinterpret_cast<type*>(value), size);
- }
-
- const A& allocator() const BOOST_NOEXCEPT {
+ A& allocator() BOOST_SP_NOEXCEPT {
return allocator_;
}
- std::size_t size() const BOOST_NOEXCEPT {
- return size_;
+ BOOST_CONSTEXPR std::size_t size() const BOOST_SP_NOEXCEPT {
+ return N;
}
private:
A allocator_;
- std::size_t size_;
- void** result_;
};
-template<class T, class U, class V>
-inline bool
-operator==(const sp_array_allocator<T, U>& first,
- const sp_array_allocator<T, V>& second) BOOST_NOEXCEPT
-{
- return first.allocator() == second.allocator() &&
- first.size() == second.size();
-}
-
-template<class T, class U, class V>
-inline bool
-operator!=(const sp_array_allocator<T, U>& first,
- const sp_array_allocator<T, V>& second) BOOST_NOEXCEPT
-{
- return !(first == second);
-}
-
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
-template<class A, class T, std::size_t N>
-struct sp_select_size_deleter {
- typedef sp_size_array_destroyer<T, N,
- typename sp_bind_allocator<A, T>::type> type;
+template<class A>
+struct sp_use_construct {
+ enum {
+ value = true
+ };
};
-template<class U, class T, std::size_t N>
-struct sp_select_size_deleter<std::allocator<U>, T, N> {
- typedef sp_size_array_deleter<T, N> type;
+template<class T>
+struct sp_use_construct<std::allocator<T> > {
+ enum {
+ value = false
+ };
};
-
-template<class A, class T>
-struct sp_select_deleter {
- typedef sp_array_destroyer<T,
- typename sp_bind_allocator<A, T>::type> type;
+#else
+template<class>
+struct sp_use_construct {
+ enum {
+ value = false
+ };
};
+#endif
-template<class U, class T>
-struct sp_select_deleter<std::allocator<U>, T> {
- typedef sp_array_deleter<T> type;
-};
-#else
-template<class, class T, std::size_t N>
-struct sp_select_size_deleter {
- typedef sp_size_array_deleter<T, N> type;
+template<class T, class U>
+struct sp_array_alignment {
+ enum {
+ value = sp_max_size<boost::alignment_of<T>::value,
+ boost::alignment_of<U>::value>::value
+ };
};
-template<class, class T>
-struct sp_select_deleter {
- typedef sp_array_deleter<T> type;
+template<class T, class U>
+struct sp_array_offset {
+ enum {
+ value = sp_align_up<sizeof(T), sp_array_alignment<T, U>::value>::value
+ };
};
-#endif
-template<class P, class T, std::size_t N, class A>
-class sp_counted_impl_pda<P, sp_size_array_deleter<T, N>, A>
- : public sp_counted_base {
-public:
- typedef sp_size_array_deleter<T, N> deleter_type;
+template<class T, class U>
+struct sp_array_storage {
+ enum {
+ value = sp_array_alignment<T, U>::value
+ };
+ typedef typename boost::type_with_alignment<value>::type type;
+};
-private:
- typedef sp_counted_impl_pda<P, deleter_type, A> type;
- typedef typename sp_bind_allocator<A, type>::type deallocator;
+template<class T, class U>
+inline U*
+sp_array_start(void* base) BOOST_SP_NOEXCEPT
+{
+ enum {
+ size = sp_array_offset<T, U>::value
+ };
+ return reinterpret_cast<U*>(static_cast<char*>(base) + size);
+}
-public:
- sp_counted_impl_pda(P, const deleter_type&, const A& allocator)
- : deleter_(allocator),
- allocator_(allocator) { }
+template<class A, class T>
+class sp_array_creator {
+ typedef typename A::value_type scalar;
- sp_counted_impl_pda(P, const A& allocator)
- : deleter_(allocator) { }
+ enum {
+ offset = sp_array_offset<T, scalar>::value
+ };
- void dispose() {
- deleter_(0);
- }
+ typedef typename sp_array_storage<T, scalar>::type type;
- void destroy() {
- deallocator allocator(allocator_);
- this->~type();
- allocator.deallocate(this, 1);
- }
+public:
+ template<class U>
+ sp_array_creator(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
+ : other_(other),
+ size_(sp_objects<type>(offset + sizeof(scalar) * size)) { }
- void* get_deleter(const sp_typeinfo&) {
- return &reinterpret_cast<char&>(deleter_);
+ T* create() {
+ return reinterpret_cast<T*>(other_.allocate(size_));
}
- void* get_untyped_deleter() {
- return &reinterpret_cast<char&>(deleter_);
+ void destroy(T* base) {
+ other_.deallocate(reinterpret_cast<type*>(base), size_);
}
private:
- deleter_type deleter_;
- A allocator_;
+ typename sp_bind_allocator<A, type>::type other_;
+ std::size_t size_;
};
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
-template<class P, class T, std::size_t N, class U, class A>
-class sp_counted_impl_pda<P, sp_size_array_destroyer<T, N, U>, A>
- : public sp_counted_base {
-public:
- typedef sp_size_array_destroyer<T, N, U> deleter_type;
+struct sp_default { };
-private:
- typedef sp_counted_impl_pda<P, deleter_type, A> type;
- typedef typename sp_bind_allocator<A, type>::type deallocator;
+template<class T, bool E = sp_use_construct<T>::value>
+class sp_array_base
+ : public sp_counted_base {
+ typedef typename T::type allocator;
public:
- sp_counted_impl_pda(P, const deleter_type&, const A& allocator)
- : deleter_(allocator) { }
-
- sp_counted_impl_pda(P, const A& allocator)
- : deleter_(allocator) { }
+ typedef typename allocator::value_type type;
- void dispose() {
- deleter_(0);
+ template<class A>
+ sp_array_base(const A& other, std::size_t size, type* start)
+ : state_(other, size) {
+ sp_array_construct<E>(state_.allocator(), start, state_.size());
}
- void destroy() {
- deallocator allocator(deleter_.allocator());
- this->~type();
- allocator.deallocate(this, 1);
+ template<class A>
+ sp_array_base(const A& other, std::size_t size, const type* list,
+ std::size_t count, type* start)
+ : state_(other, size) {
+ sp_array_construct<E>(state_.allocator(), start, state_.size(), list,
+ count);
}
- void* get_deleter(const sp_typeinfo&) {
- return &reinterpret_cast<char&>(deleter_);
+ template<class A>
+ sp_array_base(sp_default, const A& other, std::size_t size, type* start)
+ : state_(other, size) {
+ sp_array_default(state_.allocator(), start, state_.size());
}
- void* get_untyped_deleter() {
- return &reinterpret_cast<char&>(deleter_);
+ T& state() BOOST_SP_NOEXCEPT {
+ return state_;
}
-private:
- deleter_type deleter_;
-};
-#endif
-
-template<class P, class T, class A>
-class sp_counted_impl_pda<P, sp_array_deleter<T>,
- sp_array_allocator<T, A> >
- : public sp_counted_base {
-public:
- typedef sp_array_deleter<T> deleter_type;
- typedef sp_array_allocator<T, A> allocator_type;
-
-private:
- typedef sp_counted_impl_pda<P, deleter_type, allocator_type> type;
- typedef sp_array_allocator<T,
- typename sp_bind_allocator<A, type>::type> deallocator;
-
-public:
- sp_counted_impl_pda(P, const deleter_type&,
- const allocator_type& allocator)
- : deleter_(allocator),
- allocator_(allocator.allocator()) { }
-
- sp_counted_impl_pda(P, const allocator_type& allocator)
- : deleter_(allocator),
- allocator_(allocator.allocator()) { }
+ virtual void dispose() {
+ sp_array_destroy<E>(state_.allocator(),
+ sp_array_start<sp_array_base, type>(this), state_.size());
+ }
- void dispose() {
- deleter_(0);
+ virtual void destroy() {
+ sp_array_creator<allocator, sp_array_base> other(state_.allocator(),
+ state_.size());
+ this->~sp_array_base();
+ other.destroy(this);
}
- void destroy() {
- deallocator allocator(allocator_, deleter_.size());
- this->~type();
- allocator.deallocate(this, 1);
+ virtual void* get_deleter(const sp_typeinfo&) {
+ return 0;
}
- void* get_deleter(const sp_typeinfo&) {
- return &reinterpret_cast<char&>(deleter_);
+ virtual void* get_local_deleter(const sp_typeinfo&) {
+ return 0;
}
- void* get_untyped_deleter() {
- return &reinterpret_cast<char&>(deleter_);
+ virtual void* get_untyped_deleter() {
+ return 0;
}
private:
- deleter_type deleter_;
- A allocator_;
+ T state_;
};
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
-template<class P, class T, class U, class A>
-class sp_counted_impl_pda<P, sp_array_destroyer<T, U>,
- sp_array_allocator<T, A> >
- : public sp_counted_base {
-public:
- typedef sp_array_destroyer<T, U> deleter_type;
- typedef sp_array_allocator<T, A> allocator_type;
-
-private:
- typedef sp_counted_impl_pda<P, deleter_type, allocator_type> type;
- typedef sp_array_allocator<T,
- typename sp_bind_allocator<A, type>::type> deallocator;
-
+template<class A, class T>
+struct sp_array_result {
public:
- sp_counted_impl_pda(P, const deleter_type&,
- const allocator_type& allocator)
- : deleter_(allocator) { }
-
- sp_counted_impl_pda(P, const allocator_type& allocator)
- : deleter_(allocator) { }
-
- void dispose() {
- deleter_(0);
- }
+ template<class U>
+ sp_array_result(const U& other, std::size_t size)
+ : creator_(other, size),
+ result_(creator_.create()) { }
- void destroy() {
- deallocator allocator(deleter_.allocator(), deleter_.size());
- this->~type();
- allocator.deallocate(this, 1);
+ ~sp_array_result() {
+ if (result_) {
+ creator_.destroy(result_);
+ }
}
- void* get_deleter(const sp_typeinfo&) {
- return &reinterpret_cast<char&>(deleter_);
+ T* get() const {
+ return result_;
}
- void* get_untyped_deleter() {
- return &reinterpret_cast<char&>(deleter_);
+ void release() {
+ result_ = 0;
}
private:
- deleter_type deleter_;
+ sp_array_result(const sp_array_result&);
+ sp_array_result& operator=(const sp_array_result&);
+
+ sp_array_creator<A, T> creator_;
+ T* result_;
};
-#endif
} /* detail */
template<class T, class A>
-inline typename detail::sp_if_size_array<T>::type
-allocate_shared(const A& allocator)
+inline typename detail::sp_if_array<T>::type
+allocate_shared(const A& allocator, std::size_t count)
{
typedef typename detail::sp_array_element<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
- typedef typename detail::sp_select_size_deleter<A, scalar,
- detail::sp_array_count<T>::value>::type deleter;
- shared_ptr<T> result(static_cast<type*>(0),
- detail::sp_inplace_tag<deleter>(), allocator);
- deleter* state = detail::sp_get_deleter<deleter>(result);
- void* start = state->construct();
- return shared_ptr<T>(result, static_cast<type*>(start));
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::sp_array_state<other> state;
+ typedef detail::sp_array_base<state> base;
+ std::size_t size = count * detail::sp_array_count<type>::value;
+ detail::sp_array_result<other, base> result(allocator, size);
+ detail::sp_counted_base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(allocator, size, start);
+ result.release();
+ return shared_ptr<T>(detail::sp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), detail::shared_count(node));
}
template<class T, class A>
inline typename detail::sp_if_size_array<T>::type
-allocate_shared(const A& allocator,
- const typename detail::sp_array_element<T>::type& value)
+allocate_shared(const A& allocator)
{
+ enum {
+ size = detail::sp_array_count<T>::value
+ };
typedef typename detail::sp_array_element<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
- typedef typename detail::sp_select_size_deleter<A, scalar,
- detail::sp_array_count<T>::value>::type deleter;
- shared_ptr<T> result(static_cast<type*>(0),
- detail::sp_inplace_tag<deleter>(), allocator);
- deleter* state = detail::sp_get_deleter<deleter>(result);
- void* start = state->construct(reinterpret_cast<const
- scalar*>(&value), detail::sp_array_count<type>::value);
- return shared_ptr<T>(result, static_cast<type*>(start));
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::sp_size_array_state<other, size> state;
+ typedef detail::sp_array_base<state> base;
+ detail::sp_array_result<other, base> result(allocator, size);
+ detail::sp_counted_base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(allocator, size, start);
+ result.release();
+ return shared_ptr<T>(detail::sp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), detail::shared_count(node));
}
template<class T, class A>
-inline typename detail::sp_if_size_array<T>::type
-allocate_shared_noinit(const A& allocator)
+inline typename detail::sp_if_array<T>::type
+allocate_shared(const A& allocator, std::size_t count,
+ const typename detail::sp_array_element<T>::type& value)
{
typedef typename detail::sp_array_element<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
- typedef detail::sp_size_array_deleter<scalar,
- detail::sp_array_count<T>::value> deleter;
- shared_ptr<T> result(static_cast<type*>(0),
- detail::sp_inplace_tag<deleter>(), allocator);
- deleter* state = detail::sp_get_deleter<deleter>(result);
- void* start = state->construct_default();
- return shared_ptr<T>(result, static_cast<type*>(start));
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::sp_array_state<other> state;
+ typedef detail::sp_array_base<state> base;
+ std::size_t size = count * detail::sp_array_count<type>::value;
+ detail::sp_array_result<other, base> result(allocator, size);
+ detail::sp_counted_base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(allocator, size,
+ reinterpret_cast<const scalar*>(&value),
+ detail::sp_array_count<type>::value, start);
+ result.release();
+ return shared_ptr<T>(detail::sp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), detail::shared_count(node));
}
template<class T, class A>
-inline typename detail::sp_if_array<T>::type
-allocate_shared(const A& allocator, std::size_t count)
+inline typename detail::sp_if_size_array<T>::type
+allocate_shared(const A& allocator,
+ const typename detail::sp_array_element<T>::type& value)
{
+ enum {
+ size = detail::sp_array_count<T>::value
+ };
typedef typename detail::sp_array_element<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
- typedef typename detail::sp_select_deleter<A, scalar>::type deleter;
- std::size_t size = count * detail::sp_array_count<type>::value;
- void* start;
- shared_ptr<T> result(static_cast<type*>(0),
- detail::sp_inplace_tag<deleter>(),
- detail::sp_array_allocator<scalar, A>(allocator, size, &start));
- deleter* state = detail::sp_get_deleter<deleter>(result);
- state->construct(static_cast<scalar*>(start));
- return shared_ptr<T>(result, static_cast<type*>(start));
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::sp_size_array_state<other, size> state;
+ typedef detail::sp_array_base<state> base;
+ detail::sp_array_result<other, base> result(allocator, size);
+ detail::sp_counted_base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(allocator, size,
+ reinterpret_cast<const scalar*>(&value),
+ detail::sp_array_count<type>::value, start);
+ result.release();
+ return shared_ptr<T>(detail::sp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), detail::shared_count(node));
}
template<class T, class A>
inline typename detail::sp_if_array<T>::type
-allocate_shared(const A& allocator, std::size_t count,
- const typename detail::sp_array_element<T>::type& value)
+allocate_shared_noinit(const A& allocator, std::size_t count)
{
typedef typename detail::sp_array_element<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
- typedef typename detail::sp_select_deleter<A, scalar>::type deleter;
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::sp_array_state<other> state;
+ typedef detail::sp_array_base<state, false> base;
std::size_t size = count * detail::sp_array_count<type>::value;
- void* start;
- shared_ptr<T> result(static_cast<type*>(0),
- detail::sp_inplace_tag<deleter>(),
- detail::sp_array_allocator<scalar, A>(allocator, size, &start));
- deleter* state = detail::sp_get_deleter<deleter>(result);
- state->construct(static_cast<scalar*>(start),
- reinterpret_cast<const scalar*>(&value),
- detail::sp_array_count<type>::value);
- return shared_ptr<T>(result, static_cast<type*>(start));
+ detail::sp_array_result<other, base> result(allocator, size);
+ detail::sp_counted_base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
+ size, start);
+ result.release();
+ return shared_ptr<T>(detail::sp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), detail::shared_count(node));
}
template<class T, class A>
-inline typename detail::sp_if_array<T>::type
-allocate_shared_noinit(const A& allocator, std::size_t count)
+inline typename detail::sp_if_size_array<T>::type
+allocate_shared_noinit(const A& allocator)
{
+ enum {
+ size = detail::sp_array_count<T>::value
+ };
typedef typename detail::sp_array_element<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
- typedef detail::sp_array_deleter<scalar> deleter;
- std::size_t size = count * detail::sp_array_count<type>::value;
- void* start;
- shared_ptr<T> result(static_cast<type*>(0),
- detail::sp_inplace_tag<deleter>(),
- detail::sp_array_allocator<scalar, A>(allocator, size, &start));
- deleter* state = detail::sp_get_deleter<deleter>(result);
- state->construct_default(static_cast<scalar*>(start));
- return shared_ptr<T>(result, static_cast<type*>(start));
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::sp_size_array_state<other, size> state;
+ typedef detail::sp_array_base<state, false> base;
+ detail::sp_array_result<other, base> result(allocator, size);
+ detail::sp_counted_base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
+ size, start);
+ result.release();
+ return shared_ptr<T>(detail::sp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), detail::shared_count(node));
}
} /* boost */
diff --git a/boost/smart_ptr/atomic_shared_ptr.hpp b/boost/smart_ptr/atomic_shared_ptr.hpp
new file mode 100644
index 0000000000..d1efa8e280
--- /dev/null
+++ b/boost/smart_ptr/atomic_shared_ptr.hpp
@@ -0,0 +1,183 @@
+#ifndef BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED
+#define BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED
+
+//
+// atomic_shared_ptr.hpp
+//
+// 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)
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+//
+
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/detail/spinlock.hpp>
+#include <cstring>
+
+namespace boost
+{
+
+template<class T> class atomic_shared_ptr
+{
+private:
+
+ boost::shared_ptr<T> p_;
+
+ mutable boost::detail::spinlock l_;
+
+ atomic_shared_ptr(const atomic_shared_ptr&);
+ atomic_shared_ptr& operator=(const atomic_shared_ptr&);
+
+private:
+
+ bool compare_exchange( shared_ptr<T>& v, shared_ptr<T> w ) BOOST_SP_NOEXCEPT
+ {
+ l_.lock();
+
+ if( p_._internal_equiv( v ) )
+ {
+ p_.swap( w );
+
+ l_.unlock();
+ return true;
+ }
+ else
+ {
+ shared_ptr<T> tmp( p_ );
+
+ l_.unlock();
+
+ tmp.swap( v );
+ return false;
+ }
+ }
+
+public:
+
+#if !defined( BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX ) && !defined( BOOST_NO_CXX11_CONSTEXPR )
+
+ constexpr atomic_shared_ptr() BOOST_SP_NOEXCEPT: l_ BOOST_DETAIL_SPINLOCK_INIT
+ {
+ }
+
+#else
+
+ atomic_shared_ptr() BOOST_SP_NOEXCEPT
+ {
+ boost::detail::spinlock init = BOOST_DETAIL_SPINLOCK_INIT;
+ std::memcpy( &l_, &init, sizeof( init ) );
+ }
+
+#endif
+
+ atomic_shared_ptr( shared_ptr<T> p ) BOOST_SP_NOEXCEPT
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+ : p_( std::move( p ) )
+#else
+ : p_( p )
+#endif
+ {
+ boost::detail::spinlock init = BOOST_DETAIL_SPINLOCK_INIT;
+ std::memcpy( &l_, &init, sizeof( init ) );
+ }
+
+ atomic_shared_ptr& operator=( shared_ptr<T> r ) BOOST_SP_NOEXCEPT
+ {
+ boost::detail::spinlock::scoped_lock lock( l_ );
+ p_.swap( r );
+
+ return *this;
+ }
+
+ BOOST_CONSTEXPR bool is_lock_free() const BOOST_SP_NOEXCEPT
+ {
+ return false;
+ }
+
+ shared_ptr<T> load( int = 0 ) const BOOST_SP_NOEXCEPT
+ {
+ boost::detail::spinlock::scoped_lock lock( l_ );
+ return p_;
+ }
+
+ operator shared_ptr<T>() const BOOST_SP_NOEXCEPT
+ {
+ boost::detail::spinlock::scoped_lock lock( l_ );
+ return p_;
+ }
+
+ void store( shared_ptr<T> r, int = 0 ) BOOST_SP_NOEXCEPT
+ {
+ boost::detail::spinlock::scoped_lock lock( l_ );
+ p_.swap( r );
+ }
+
+ shared_ptr<T> exchange( shared_ptr<T> r, int = 0 ) BOOST_SP_NOEXCEPT
+ {
+ {
+ boost::detail::spinlock::scoped_lock lock( l_ );
+ p_.swap( r );
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ return std::move( r );
+
+#else
+
+ return r;
+
+#endif
+ }
+
+ bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) BOOST_SP_NOEXCEPT
+ {
+ return compare_exchange( v, w );
+ }
+
+ bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) BOOST_SP_NOEXCEPT
+ {
+ return compare_exchange( v, w );
+ }
+
+ bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) BOOST_SP_NOEXCEPT
+ {
+ return compare_exchange( v, w );
+ }
+
+ bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) BOOST_SP_NOEXCEPT
+ {
+ return compare_exchange( v, w );
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) BOOST_SP_NOEXCEPT
+ {
+ return compare_exchange( v, std::move( w ) );
+ }
+
+ bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) BOOST_SP_NOEXCEPT
+ {
+ return compare_exchange( v, std::move( w ) );
+ }
+
+ bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) BOOST_SP_NOEXCEPT
+ {
+ return compare_exchange( v, std::move( w ) );
+ }
+
+ bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) BOOST_SP_NOEXCEPT
+ {
+ return compare_exchange( v, std::move( w ) );
+ }
+
+#endif
+};
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED
diff --git a/boost/smart_ptr/bad_weak_ptr.hpp b/boost/smart_ptr/bad_weak_ptr.hpp
index 582fad8b71..b086be595f 100644
--- a/boost/smart_ptr/bad_weak_ptr.hpp
+++ b/boost/smart_ptr/bad_weak_ptr.hpp
@@ -17,6 +17,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
+#include <boost/config.hpp>
#include <exception>
#ifdef __BORLANDC__
@@ -36,7 +37,8 @@ namespace boost
# pragma option push -pc
#endif
-#if defined(__clang__)
+#if defined(BOOST_CLANG)
+// Intel C++ on Mac defines __clang__ but doesn't support the pragma
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wweak-vtables"
#endif
@@ -51,7 +53,7 @@ public:
}
};
-#if defined(__clang__)
+#if defined(BOOST_CLANG)
# pragma clang diagnostic pop
#endif
diff --git a/boost/smart_ptr/detail/atomic_count_gcc.hpp b/boost/smart_ptr/detail/atomic_count_gcc.hpp
index 54807e944e..df7e32365f 100644
--- a/boost/smart_ptr/detail/atomic_count_gcc.hpp
+++ b/boost/smart_ptr/detail/atomic_count_gcc.hpp
@@ -9,7 +9,7 @@
// http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html
//
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
-// Copyright (c) 2002 Lars Gullik Bjønnes <larsbj@lyx.org>
+// Copyright (c) 2002 Lars Gullik Bjønnes <larsbj@lyx.org>
// Copyright 2003-2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
diff --git a/boost/smart_ptr/detail/local_counted_base.hpp b/boost/smart_ptr/detail/local_counted_base.hpp
new file mode 100644
index 0000000000..398b46dd1a
--- /dev/null
+++ b/boost/smart_ptr/detail/local_counted_base.hpp
@@ -0,0 +1,146 @@
+#ifndef BOOST_SMART_PTR_DETAIL_LOCAL_COUNTED_BASE_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_LOCAL_COUNTED_BASE_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// detail/local_counted_base.hpp
+//
+// 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)
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+
+#include <boost/smart_ptr/detail/shared_count.hpp>
+#include <boost/config.hpp>
+#include <utility>
+
+namespace boost
+{
+
+namespace detail
+{
+
+class local_counted_base
+{
+private:
+
+ local_counted_base & operator= ( local_counted_base const & );
+
+private:
+
+ // not 'int' or 'unsigned' to avoid aliasing and enable optimizations
+ enum count_type { min_ = 0, initial_ = 1, max_ = 2147483647 };
+
+ count_type local_use_count_;
+
+public:
+
+ BOOST_CONSTEXPR local_counted_base() BOOST_SP_NOEXCEPT: local_use_count_( initial_ )
+ {
+ }
+
+ BOOST_CONSTEXPR local_counted_base( local_counted_base const & ) BOOST_SP_NOEXCEPT: local_use_count_( initial_ )
+ {
+ }
+
+ virtual ~local_counted_base() /*BOOST_SP_NOEXCEPT*/
+ {
+ }
+
+ virtual void local_cb_destroy() BOOST_SP_NOEXCEPT = 0;
+
+ virtual boost::detail::shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT = 0;
+
+ void add_ref() BOOST_SP_NOEXCEPT
+ {
+#if defined( __has_builtin )
+# if __has_builtin( __builtin_assume )
+
+ __builtin_assume( local_use_count_ >= 1 );
+
+# endif
+#endif
+
+ local_use_count_ = static_cast<count_type>( local_use_count_ + 1 );
+ }
+
+ void release() BOOST_SP_NOEXCEPT
+ {
+ local_use_count_ = static_cast<count_type>( local_use_count_ - 1 );
+
+ if( local_use_count_ == 0 )
+ {
+ local_cb_destroy();
+ }
+ }
+
+ long local_use_count() const BOOST_SP_NOEXCEPT
+ {
+ return local_use_count_;
+ }
+};
+
+class local_counted_impl: public local_counted_base
+{
+private:
+
+ local_counted_impl( local_counted_impl const & );
+
+private:
+
+ shared_count pn_;
+
+public:
+
+ explicit local_counted_impl( shared_count const& pn ): pn_( pn )
+ {
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ explicit local_counted_impl( shared_count && pn ): pn_( std::move(pn) )
+ {
+ }
+
+#endif
+
+ virtual void local_cb_destroy() BOOST_SP_NOEXCEPT
+ {
+ delete this;
+ }
+
+ virtual boost::detail::shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT
+ {
+ return pn_;
+ }
+};
+
+class local_counted_impl_em: public local_counted_base
+{
+public:
+
+ shared_count pn_;
+
+ virtual void local_cb_destroy() BOOST_SP_NOEXCEPT
+ {
+ shared_count().swap( pn_ );
+ }
+
+ virtual boost::detail::shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT
+ {
+ return pn_;
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_LOCAL_COUNTED_BASE_HPP_INCLUDED
diff --git a/boost/smart_ptr/detail/local_sp_deleter.hpp b/boost/smart_ptr/detail/local_sp_deleter.hpp
new file mode 100644
index 0000000000..7d04f1dc52
--- /dev/null
+++ b/boost/smart_ptr/detail/local_sp_deleter.hpp
@@ -0,0 +1,91 @@
+#ifndef BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// detail/local_sp_deleter.hpp
+//
+// 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)
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+
+#include <boost/smart_ptr/detail/local_counted_base.hpp>
+#include <boost/config.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+template<class D> class local_sp_deleter: public local_counted_impl_em
+{
+private:
+
+ D d_;
+
+public:
+
+ local_sp_deleter(): d_()
+ {
+ }
+
+ explicit local_sp_deleter( D const& d ) BOOST_SP_NOEXCEPT: d_( d )
+ {
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ explicit local_sp_deleter( D&& d ) BOOST_SP_NOEXCEPT: d_( std::move(d) )
+ {
+ }
+
+#endif
+
+ D& deleter()
+ {
+ return d_;
+ }
+
+ template<class Y> void operator()( Y* p ) BOOST_SP_NOEXCEPT
+ {
+ d_( p );
+ }
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+ void operator()( boost::detail::sp_nullptr_t p ) BOOST_SP_NOEXCEPT
+ {
+ d_( p );
+ }
+
+#endif
+};
+
+template<> class local_sp_deleter<void>
+{
+};
+
+template<class D> D * get_local_deleter( local_sp_deleter<D> * p )
+{
+ return &p->deleter();
+}
+
+inline void * get_local_deleter( local_sp_deleter<void> * /*p*/ )
+{
+ return 0;
+}
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED
diff --git a/boost/smart_ptr/detail/lwm_win32_cs.hpp b/boost/smart_ptr/detail/lwm_win32_cs.hpp
index a93cf09208..7d3e156166 100644
--- a/boost/smart_ptr/detail/lwm_win32_cs.hpp
+++ b/boost/smart_ptr/detail/lwm_win32_cs.hpp
@@ -21,7 +21,13 @@
#include <boost/predef.h>
#ifdef BOOST_USE_WINDOWS_H
-# include <windows.h>
+
+#include <windows.h>
+
+#else
+
+struct _RTL_CRITICAL_SECTION;
+
#endif
namespace boost
@@ -47,13 +53,13 @@ struct critical_section
};
#if BOOST_PLAT_WINDOWS_RUNTIME
-extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSectionEx(critical_section *, unsigned long, unsigned long);
+extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSectionEx(::_RTL_CRITICAL_SECTION *, unsigned long, unsigned long);
#else
-extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(critical_section *);
+extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(::_RTL_CRITICAL_SECTION *);
#endif
-extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(critical_section *);
-extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(critical_section *);
-extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(critical_section *);
+extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(::_RTL_CRITICAL_SECTION *);
+extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(::_RTL_CRITICAL_SECTION *);
+extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(::_RTL_CRITICAL_SECTION *);
#else
@@ -75,15 +81,15 @@ public:
lightweight_mutex()
{
#if BOOST_PLAT_WINDOWS_RUNTIME
- InitializeCriticalSectionEx(&cs_, 4000, 0);
+ boost::detail::InitializeCriticalSectionEx(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&cs_), 4000, 0);
#else
- InitializeCriticalSection(&cs_);
+ boost::detail::InitializeCriticalSection(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&cs_));
#endif
}
~lightweight_mutex()
{
- DeleteCriticalSection(&cs_);
+ boost::detail::DeleteCriticalSection(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&cs_));
}
class scoped_lock;
@@ -102,12 +108,12 @@ public:
explicit scoped_lock(lightweight_mutex & m): m_(m)
{
- EnterCriticalSection(&m_.cs_);
+ boost::detail::EnterCriticalSection(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_.cs_));
}
~scoped_lock()
{
- LeaveCriticalSection(&m_.cs_);
+ boost::detail::LeaveCriticalSection(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_.cs_));
}
};
};
diff --git a/boost/smart_ptr/detail/operator_bool.hpp b/boost/smart_ptr/detail/operator_bool.hpp
index c0289b870b..f9c5ef6803 100644
--- a/boost/smart_ptr/detail/operator_bool.hpp
+++ b/boost/smart_ptr/detail/operator_bool.hpp
@@ -9,14 +9,14 @@
#if !defined( BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS ) && !defined( BOOST_NO_CXX11_NULLPTR )\
&& !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130))
- explicit operator bool () const BOOST_NOEXCEPT
+ explicit operator bool () const BOOST_SP_NOEXCEPT
{
return px != 0;
}
#elif ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__)
- operator bool () const BOOST_NOEXCEPT
+ operator bool () const BOOST_SP_NOEXCEPT
{
return px != 0;
}
@@ -29,7 +29,7 @@
typedef void (*unspecified_bool_type)( this_type*** );
- operator unspecified_bool_type() const BOOST_NOEXCEPT
+ operator unspecified_bool_type() const BOOST_SP_NOEXCEPT
{
return px == 0? 0: unspecified_bool;
}
@@ -41,7 +41,7 @@
typedef element_type * (this_type::*unspecified_bool_type)() const;
- operator unspecified_bool_type() const BOOST_NOEXCEPT
+ operator unspecified_bool_type() const BOOST_SP_NOEXCEPT
{
return px == 0? 0: &this_type::get;
}
@@ -50,7 +50,7 @@
typedef element_type * this_type::*unspecified_bool_type;
- operator unspecified_bool_type() const BOOST_NOEXCEPT
+ operator unspecified_bool_type() const BOOST_SP_NOEXCEPT
{
return px == 0? 0: &this_type::px;
}
@@ -58,7 +58,7 @@
#endif
// operator! is redundant, but some compilers need it
- bool operator! () const BOOST_NOEXCEPT
+ bool operator! () const BOOST_SP_NOEXCEPT
{
return px == 0;
}
diff --git a/boost/smart_ptr/detail/shared_count.hpp b/boost/smart_ptr/detail/shared_count.hpp
index 9813842300..ae7d0fb46f 100644
--- a/boost/smart_ptr/detail/shared_count.hpp
+++ b/boost/smart_ptr/detail/shared_count.hpp
@@ -54,7 +54,7 @@ namespace boost
namespace movelib
{
- template< class T, class D > class unique_ptr;
+template< class T, class D > class unique_ptr;
} // namespace movelib
@@ -118,7 +118,14 @@ private:
public:
- shared_count(): pi_(0) // nothrow
+ BOOST_CONSTEXPR shared_count(): pi_(0) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+ }
+
+ BOOST_CONSTEXPR explicit shared_count( sp_counted_base * pi ): pi_( pi ) // nothrow
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
@@ -496,6 +503,11 @@ public:
return pi_? pi_->get_deleter( ti ): 0;
}
+ void * get_local_deleter( sp_typeinfo const & ti ) const
+ {
+ return pi_? pi_->get_local_deleter( ti ): 0;
+ }
+
void * get_untyped_deleter() const
{
return pi_? pi_->get_untyped_deleter(): 0;
@@ -517,7 +529,7 @@ private:
public:
- weak_count(): pi_(0) // nothrow
+ BOOST_CONSTEXPR weak_count(): pi_(0) // nothrow
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(weak_count_id)
#endif
diff --git a/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp b/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp
index cebc243d2e..ec6f6ee184 100644
--- a/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp
@@ -104,6 +104,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_aix.hpp b/boost/smart_ptr/detail/sp_counted_base_aix.hpp
index fe6c727e38..ce8ee686ba 100644
--- a/boost/smart_ptr/detail/sp_counted_base_aix.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_aix.hpp
@@ -96,6 +96,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_clang.hpp b/boost/smart_ptr/detail/sp_counted_base_clang.hpp
index 75984959d3..8b3bfad9b6 100644
--- a/boost/smart_ptr/detail/sp_counted_base_clang.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_clang.hpp
@@ -98,6 +98,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp b/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp
index 6c268e8921..065f7c3d14 100644
--- a/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp
@@ -124,6 +124,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp b/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp
index 81eba6f178..3a3d4d4119 100644
--- a/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp
@@ -112,6 +112,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp b/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp
index f6e3904157..6c3cce8d44 100644
--- a/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp
@@ -111,6 +111,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp b/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp
index 545c8ae4fc..76ac2a612d 100644
--- a/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp
@@ -135,6 +135,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp b/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp
index 2e5bc0e853..0fb807488a 100644
--- a/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp
@@ -135,6 +135,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp b/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp
index c6d20ce7ea..b8bb707f1b 100644
--- a/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp
@@ -120,6 +120,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp b/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp
index 173dce5c81..3d2dd61ed6 100644
--- a/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp
@@ -127,6 +127,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_nt.hpp b/boost/smart_ptr/detail/sp_counted_base_nt.hpp
index 5c901f9d16..dea905c905 100644
--- a/boost/smart_ptr/detail/sp_counted_base_nt.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_nt.hpp
@@ -59,6 +59,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_pt.hpp b/boost/smart_ptr/detail/sp_counted_base_pt.hpp
index a16d2d8652..85f2563d5d 100644
--- a/boost/smart_ptr/detail/sp_counted_base_pt.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_pt.hpp
@@ -71,6 +71,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp b/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp
index 56ed79fa97..7b5f9178a6 100644
--- a/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp
@@ -115,6 +115,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_solaris.hpp b/boost/smart_ptr/detail/sp_counted_base_solaris.hpp
index 0e05fef4cb..0db9c6cbd5 100644
--- a/boost/smart_ptr/detail/sp_counted_base_solaris.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_solaris.hpp
@@ -62,6 +62,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_spin.hpp b/boost/smart_ptr/detail/sp_counted_base_spin.hpp
index 77734e727d..faf503ad57 100644
--- a/boost/smart_ptr/detail/sp_counted_base_spin.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_spin.hpp
@@ -84,6 +84,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp b/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp
index cab8453591..7a188f8a66 100644
--- a/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp
@@ -90,6 +90,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_sync.hpp b/boost/smart_ptr/detail/sp_counted_base_sync.hpp
index fafed0e72e..d2138e7c26 100644
--- a/boost/smart_ptr/detail/sp_counted_base_sync.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_sync.hpp
@@ -109,6 +109,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp b/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp
index 162f309b56..f2de3b02d8 100644
--- a/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp
@@ -104,6 +104,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_w32.hpp b/boost/smart_ptr/detail/sp_counted_base_w32.hpp
index 4ba509c6cd..960e42e128 100644
--- a/boost/smart_ptr/detail/sp_counted_base_w32.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_w32.hpp
@@ -67,6 +67,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_impl.hpp b/boost/smart_ptr/detail/sp_counted_impl.hpp
index b29769e3af..fa2f75eb1a 100644
--- a/boost/smart_ptr/detail/sp_counted_impl.hpp
+++ b/boost/smart_ptr/detail/sp_counted_impl.hpp
@@ -26,6 +26,7 @@
#include <boost/checked_delete.hpp>
#include <boost/smart_ptr/detail/sp_counted_base.hpp>
+#include <boost/core/addressof.hpp>
#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
#include <boost/smart_ptr/detail/quick_allocator.hpp>
@@ -50,6 +51,19 @@ void sp_scalar_destructor_hook( void * px, std::size_t size, void * pn );
namespace detail
{
+// get_local_deleter
+
+template<class D> class local_sp_deleter;
+
+template<class D> D * get_local_deleter( D * /*p*/ )
+{
+ return 0;
+}
+
+template<class D> D * get_local_deleter( local_sp_deleter<D> * p );
+
+//
+
template<class X> class sp_counted_impl_p: public sp_counted_base
{
private:
@@ -83,6 +97,11 @@ public:
return 0;
}
+ virtual void * get_local_deleter( sp_typeinfo const & )
+ {
+ return 0;
+ }
+
virtual void * get_untyped_deleter()
{
return 0;
@@ -158,6 +177,11 @@ public:
return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast<char&>( del ): 0;
}
+ virtual void * get_local_deleter( sp_typeinfo const & ti )
+ {
+ return ti == BOOST_SP_TYPEID(D)? boost::detail::get_local_deleter( boost::addressof( del ) ): 0;
+ }
+
virtual void * get_untyped_deleter()
{
return &reinterpret_cast<char&>( del );
@@ -246,6 +270,11 @@ public:
return ti == BOOST_SP_TYPEID( D )? &reinterpret_cast<char&>( d_ ): 0;
}
+ virtual void * get_local_deleter( sp_typeinfo const & ti )
+ {
+ return ti == BOOST_SP_TYPEID(D)? boost::detail::get_local_deleter( boost::addressof( d_ ) ): 0;
+ }
+
virtual void * get_untyped_deleter()
{
return &reinterpret_cast<char&>( d_ );
diff --git a/boost/smart_ptr/detail/sp_noexcept.hpp b/boost/smart_ptr/detail/sp_noexcept.hpp
index 6818dce38d..1287ba4952 100644
--- a/boost/smart_ptr/detail/sp_noexcept.hpp
+++ b/boost/smart_ptr/detail/sp_noexcept.hpp
@@ -9,7 +9,7 @@
// detail/sp_noexcept.hpp
//
-// Copyright 2016 Peter Dimov
+// Copyright 2016, 2017 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
@@ -17,13 +17,31 @@
#include <boost/config.hpp>
+// BOOST_SP_NOEXCEPT
+
#if defined( BOOST_MSVC ) && BOOST_MSVC >= 1700 && BOOST_MSVC < 1900
-#define BOOST_SP_NOEXCEPT BOOST_NOEXCEPT_OR_NOTHROW
+# define BOOST_SP_NOEXCEPT BOOST_NOEXCEPT_OR_NOTHROW
+
+#else
+
+# define BOOST_SP_NOEXCEPT BOOST_NOEXCEPT
+
+#endif
+
+// BOOST_SP_NOEXCEPT_WITH_ASSERT
+
+#if defined(BOOST_DISABLE_ASSERTS) || ( defined(BOOST_ENABLE_ASSERT_DEBUG_HANDLER) && defined(NDEBUG) )
+
+# define BOOST_SP_NOEXCEPT_WITH_ASSERT BOOST_SP_NOEXCEPT
+
+#elif defined(BOOST_ENABLE_ASSERT_HANDLER) || ( defined(BOOST_ENABLE_ASSERT_DEBUG_HANDLER) && !defined(NDEBUG) )
+
+# define BOOST_SP_NOEXCEPT_WITH_ASSERT
#else
-#define BOOST_SP_NOEXCEPT BOOST_NOEXCEPT
+# define BOOST_SP_NOEXCEPT_WITH_ASSERT BOOST_SP_NOEXCEPT
#endif
diff --git a/boost/smart_ptr/detail/yield_k.hpp b/boost/smart_ptr/detail/yield_k.hpp
index 44d1836478..f8ca6b6467 100644
--- a/boost/smart_ptr/detail/yield_k.hpp
+++ b/boost/smart_ptr/detail/yield_k.hpp
@@ -33,7 +33,7 @@
// BOOST_SMT_PAUSE
-#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) )
+#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) ) && !defined(__c2__)
extern "C" void _mm_pause();
diff --git a/boost/smart_ptr/enable_shared_from_this.hpp b/boost/smart_ptr/enable_shared_from_this.hpp
index 642403a0a3..fc4de0b571 100644
--- a/boost/smart_ptr/enable_shared_from_this.hpp
+++ b/boost/smart_ptr/enable_shared_from_this.hpp
@@ -10,7 +10,7 @@
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
-// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
//
#include <boost/smart_ptr/weak_ptr.hpp>
@@ -26,11 +26,11 @@ template<class T> class enable_shared_from_this
{
protected:
- enable_shared_from_this() BOOST_SP_NOEXCEPT
+ BOOST_CONSTEXPR enable_shared_from_this() BOOST_SP_NOEXCEPT
{
}
- enable_shared_from_this(enable_shared_from_this const &) BOOST_SP_NOEXCEPT
+ BOOST_CONSTEXPR enable_shared_from_this(enable_shared_from_this const &) BOOST_SP_NOEXCEPT
{
}
@@ -59,12 +59,12 @@ public:
return p;
}
- weak_ptr<T> weak_from_this() BOOST_NOEXCEPT
+ weak_ptr<T> weak_from_this() BOOST_SP_NOEXCEPT
{
return weak_this_;
}
- weak_ptr<T const> weak_from_this() const BOOST_NOEXCEPT
+ weak_ptr<T const> weak_from_this() const BOOST_SP_NOEXCEPT
{
return weak_this_;
}
@@ -72,7 +72,7 @@ public:
public: // actually private, but avoids compiler template friendship issues
// Note: invoked automatically by shared_ptr; do not call
- template<class X, class Y> void _internal_accept_owner( shared_ptr<X> const * ppx, Y * py ) const
+ template<class X, class Y> void _internal_accept_owner( shared_ptr<X> const * ppx, Y * py ) const BOOST_SP_NOEXCEPT
{
if( weak_this_.expired() )
{
diff --git a/boost/smart_ptr/intrusive_ptr.hpp b/boost/smart_ptr/intrusive_ptr.hpp
index 0e46212165..0ab075d367 100644
--- a/boost/smart_ptr/intrusive_ptr.hpp
+++ b/boost/smart_ptr/intrusive_ptr.hpp
@@ -6,11 +6,11 @@
//
// 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)
+// Distributed under the 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/intrusive_ptr.html for documentation.
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
//
#include <boost/config.hpp>
@@ -141,7 +141,7 @@ public:
}
template<class U>
- intrusive_ptr & operator=(intrusive_ptr<U> && rhs) BOOST_NOEXCEPT
+ intrusive_ptr & operator=(intrusive_ptr<U> && rhs) BOOST_SP_NOEXCEPT
{
this_type( static_cast< intrusive_ptr<U> && >( rhs ) ).swap(*this);
return *this;
@@ -161,7 +161,7 @@ public:
return *this;
}
- void reset() BOOST_NOEXCEPT
+ void reset()
{
this_type().swap( *this );
}
@@ -176,25 +176,25 @@ public:
this_type( rhs, add_ref ).swap( *this );
}
- T * get() const BOOST_NOEXCEPT
+ T * get() const BOOST_SP_NOEXCEPT
{
return px;
}
- T * detach() BOOST_NOEXCEPT
+ T * detach() BOOST_SP_NOEXCEPT
{
T * ret = px;
px = 0;
return ret;
}
- T & operator*() const
+ T & operator*() const BOOST_SP_NOEXCEPT_WITH_ASSERT
{
BOOST_ASSERT( px != 0 );
return *px;
}
- T * operator->() const
+ T * operator->() const BOOST_SP_NOEXCEPT_WITH_ASSERT
{
BOOST_ASSERT( px != 0 );
return px;
@@ -203,7 +203,7 @@ public:
// implicit conversion to "bool"
#include <boost/smart_ptr/detail/operator_bool.hpp>
- void swap(intrusive_ptr & rhs) BOOST_NOEXCEPT
+ void swap(intrusive_ptr & rhs) BOOST_SP_NOEXCEPT
{
T * tmp = px;
px = rhs.px;
@@ -215,32 +215,32 @@ private:
T * px;
};
-template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
+template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) BOOST_SP_NOEXCEPT
{
return a.get() == b.get();
}
-template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
+template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) BOOST_SP_NOEXCEPT
{
return a.get() != b.get();
}
-template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, U * b)
+template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, U * b) BOOST_SP_NOEXCEPT
{
return a.get() == b;
}
-template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, U * b)
+template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, U * b) BOOST_SP_NOEXCEPT
{
return a.get() != b;
}
-template<class T, class U> inline bool operator==(T * a, intrusive_ptr<U> const & b)
+template<class T, class U> inline bool operator==(T * a, intrusive_ptr<U> const & b) BOOST_SP_NOEXCEPT
{
return a == b.get();
}
-template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const & b)
+template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const & b) BOOST_SP_NOEXCEPT
{
return a != b.get();
}
@@ -249,7 +249,7 @@ template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const
// Resolve the ambiguity between our op!= and the one in rel_ops
-template<class T> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b)
+template<class T> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) BOOST_SP_NOEXCEPT
{
return a.get() != b.get();
}
@@ -258,41 +258,41 @@ template<class T> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_p
#if !defined( BOOST_NO_CXX11_NULLPTR )
-template<class T> inline bool operator==( intrusive_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
+template<class T> inline bool operator==( intrusive_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
{
return p.get() == 0;
}
-template<class T> inline bool operator==( boost::detail::sp_nullptr_t, intrusive_ptr<T> const & p ) BOOST_NOEXCEPT
+template<class T> inline bool operator==( boost::detail::sp_nullptr_t, intrusive_ptr<T> const & p ) BOOST_SP_NOEXCEPT
{
return p.get() == 0;
}
-template<class T> inline bool operator!=( intrusive_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
+template<class T> inline bool operator!=( intrusive_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
{
return p.get() != 0;
}
-template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, intrusive_ptr<T> const & p ) BOOST_NOEXCEPT
+template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, intrusive_ptr<T> const & p ) BOOST_SP_NOEXCEPT
{
return p.get() != 0;
}
#endif
-template<class T> inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b)
+template<class T> inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) BOOST_SP_NOEXCEPT
{
return std::less<T *>()(a.get(), b.get());
}
-template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs)
+template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs) BOOST_SP_NOEXCEPT
{
lhs.swap(rhs);
}
// mem_fn support
-template<class T> T * get_pointer(intrusive_ptr<T> const & p)
+template<class T> T * get_pointer(intrusive_ptr<T> const & p) BOOST_SP_NOEXCEPT
{
return p.get();
}
@@ -351,7 +351,7 @@ template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::
template< class T > struct hash;
-template< class T > std::size_t hash_value( boost::intrusive_ptr<T> const & p )
+template< class T > std::size_t hash_value( boost::intrusive_ptr<T> const & p ) BOOST_SP_NOEXCEPT
{
return boost::hash< T* >()( p.get() );
}
diff --git a/boost/smart_ptr/intrusive_ref_counter.hpp b/boost/smart_ptr/intrusive_ref_counter.hpp
index b7587ea7a0..c2f918d0a4 100644
--- a/boost/smart_ptr/intrusive_ref_counter.hpp
+++ b/boost/smart_ptr/intrusive_ref_counter.hpp
@@ -17,6 +17,7 @@
#include <boost/config.hpp>
#include <boost/smart_ptr/detail/atomic_count.hpp>
+#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -45,17 +46,17 @@ struct thread_unsafe_counter
{
typedef unsigned int type;
- static unsigned int load(unsigned int const& counter) BOOST_NOEXCEPT
+ static unsigned int load(unsigned int const& counter) BOOST_SP_NOEXCEPT
{
return counter;
}
- static void increment(unsigned int& counter) BOOST_NOEXCEPT
+ static void increment(unsigned int& counter) BOOST_SP_NOEXCEPT
{
++counter;
}
- static unsigned int decrement(unsigned int& counter) BOOST_NOEXCEPT
+ static unsigned int decrement(unsigned int& counter) BOOST_SP_NOEXCEPT
{
return --counter;
}
@@ -71,17 +72,17 @@ struct thread_safe_counter
{
typedef boost::detail::atomic_count type;
- static unsigned int load(boost::detail::atomic_count const& counter) BOOST_NOEXCEPT
+ static unsigned int load(boost::detail::atomic_count const& counter) BOOST_SP_NOEXCEPT
{
return static_cast< unsigned int >(static_cast< long >(counter));
}
- static void increment(boost::detail::atomic_count& counter) BOOST_NOEXCEPT
+ static void increment(boost::detail::atomic_count& counter) BOOST_SP_NOEXCEPT
{
++counter;
}
- static unsigned int decrement(boost::detail::atomic_count& counter) BOOST_NOEXCEPT
+ static unsigned int decrement(boost::detail::atomic_count& counter) BOOST_SP_NOEXCEPT
{
return static_cast< unsigned int >(--counter);
}
@@ -91,9 +92,9 @@ template< typename DerivedT, typename CounterPolicyT = thread_safe_counter >
class intrusive_ref_counter;
template< typename DerivedT, typename CounterPolicyT >
-void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT;
+void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
template< typename DerivedT, typename CounterPolicyT >
-void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT;
+void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
/*!
* \brief A reference counter base class
@@ -121,7 +122,7 @@ public:
*
* \post <tt>use_count() == 0</tt>
*/
- intrusive_ref_counter() BOOST_NOEXCEPT : m_ref_counter(0)
+ intrusive_ref_counter() BOOST_SP_NOEXCEPT : m_ref_counter(0)
{
}
@@ -130,7 +131,7 @@ public:
*
* \post <tt>use_count() == 0</tt>
*/
- intrusive_ref_counter(intrusive_ref_counter const&) BOOST_NOEXCEPT : m_ref_counter(0)
+ intrusive_ref_counter(intrusive_ref_counter const&) BOOST_SP_NOEXCEPT : m_ref_counter(0)
{
}
@@ -139,12 +140,12 @@ public:
*
* \post The reference counter is not modified after assignment
*/
- intrusive_ref_counter& operator= (intrusive_ref_counter const&) BOOST_NOEXCEPT { return *this; }
+ intrusive_ref_counter& operator= (intrusive_ref_counter const&) BOOST_SP_NOEXCEPT { return *this; }
/*!
* \return The reference counter
*/
- unsigned int use_count() const BOOST_NOEXCEPT
+ unsigned int use_count() const BOOST_SP_NOEXCEPT
{
return CounterPolicyT::load(m_ref_counter);
}
@@ -155,18 +156,18 @@ protected:
*/
BOOST_DEFAULTED_FUNCTION(~intrusive_ref_counter(), {})
- friend void intrusive_ptr_add_ref< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT;
- friend void intrusive_ptr_release< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT;
+ friend void intrusive_ptr_add_ref< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
+ friend void intrusive_ptr_release< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
};
template< typename DerivedT, typename CounterPolicyT >
-inline void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT
+inline void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT
{
CounterPolicyT::increment(p->m_ref_counter);
}
template< typename DerivedT, typename CounterPolicyT >
-inline void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT
+inline void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT
{
if (CounterPolicyT::decrement(p->m_ref_counter) == 0)
delete static_cast< const DerivedT* >(p);
diff --git a/boost/smart_ptr/local_shared_ptr.hpp b/boost/smart_ptr/local_shared_ptr.hpp
new file mode 100644
index 0000000000..0d1fa0182e
--- /dev/null
+++ b/boost/smart_ptr/local_shared_ptr.hpp
@@ -0,0 +1,684 @@
+#ifndef BOOST_SMART_PTR_LOCAL_SHARED_PTR_HPP_INCLUDED
+#define BOOST_SMART_PTR_LOCAL_SHARED_PTR_HPP_INCLUDED
+
+// local_shared_ptr.hpp
+//
+// 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)
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+
+#include <boost/smart_ptr/shared_ptr.hpp>
+
+namespace boost
+{
+
+template<class T> class local_shared_ptr;
+
+namespace detail
+{
+
+template< class E, class Y > inline void lsp_pointer_construct( boost::local_shared_ptr< E > * /*ppx*/, Y * p, boost::detail::local_counted_base * & pn )
+{
+ boost::detail::sp_assert_convertible< Y, E >();
+
+ typedef boost::detail::local_sp_deleter< boost::checked_deleter<Y> > D;
+
+ boost::shared_ptr<E> p2( p, D() );
+
+ D * pd = static_cast< D * >( p2._internal_get_untyped_deleter() );
+
+ pd->pn_ = p2._internal_count();
+
+ pn = pd;
+}
+
+template< class E, class Y > inline void lsp_pointer_construct( boost::local_shared_ptr< E[] > * /*ppx*/, Y * p, boost::detail::local_counted_base * & pn )
+{
+ boost::detail::sp_assert_convertible< Y[], E[] >();
+
+ typedef boost::detail::local_sp_deleter< boost::checked_array_deleter<E> > D;
+
+ boost::shared_ptr<E[]> p2( p, D() );
+
+ D * pd = static_cast< D * >( p2._internal_get_untyped_deleter() );
+
+ pd->pn_ = p2._internal_count();
+
+ pn = pd;
+}
+
+template< class E, std::size_t N, class Y > inline void lsp_pointer_construct( boost::local_shared_ptr< E[N] > * /*ppx*/, Y * p, boost::detail::local_counted_base * & pn )
+{
+ boost::detail::sp_assert_convertible< Y[N], E[N] >();
+
+ typedef boost::detail::local_sp_deleter< boost::checked_array_deleter<E> > D;
+
+ boost::shared_ptr<E[N]> p2( p, D() );
+
+ D * pd = static_cast< D * >( p2._internal_get_untyped_deleter() );
+
+ pd->pn_ = p2._internal_count();
+
+ pn = pd;
+}
+
+template< class E, class P, class D > inline void lsp_deleter_construct( boost::local_shared_ptr< E > * /*ppx*/, P p, D const& d, boost::detail::local_counted_base * & pn )
+{
+ typedef boost::detail::local_sp_deleter<D> D2;
+
+ boost::shared_ptr<E> p2( p, D2( d ) );
+
+ D2 * pd = static_cast< D2 * >( p2._internal_get_untyped_deleter() );
+
+ pd->pn_ = p2._internal_count();
+
+ pn = pd;
+}
+
+template< class E, class P, class D, class A > inline void lsp_allocator_construct( boost::local_shared_ptr< E > * /*ppx*/, P p, D const& d, A const& a, boost::detail::local_counted_base * & pn )
+{
+ typedef boost::detail::local_sp_deleter<D> D2;
+
+ boost::shared_ptr<E> p2( p, D2( d ), a );
+
+ D2 * pd = static_cast< D2 * >( p2._internal_get_untyped_deleter() );
+
+ pd->pn_ = p2._internal_count();
+
+ pn = pd;
+}
+
+struct lsp_internal_constructor_tag
+{
+};
+
+} // namespace detail
+
+//
+// local_shared_ptr
+//
+// as shared_ptr, but local to a thread.
+// reference count manipulations are non-atomic.
+//
+
+template<class T> class local_shared_ptr
+{
+private:
+
+ typedef local_shared_ptr this_type;
+
+public:
+
+ typedef typename boost::detail::sp_element<T>::type element_type;
+
+private:
+
+ element_type * px;
+ boost::detail::local_counted_base * pn;
+
+ template<class Y> friend class local_shared_ptr;
+
+public:
+
+ // destructor
+
+ ~local_shared_ptr() BOOST_SP_NOEXCEPT
+ {
+ if( pn )
+ {
+ pn->release();
+ }
+ }
+
+ // constructors
+
+ BOOST_CONSTEXPR local_shared_ptr() BOOST_SP_NOEXCEPT : px( 0 ), pn( 0 )
+ {
+ }
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+ BOOST_CONSTEXPR local_shared_ptr( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT : px( 0 ), pn( 0 )
+ {
+ }
+
+#endif
+
+ // internal constructor, used by make_shared
+ BOOST_CONSTEXPR local_shared_ptr( boost::detail::lsp_internal_constructor_tag, element_type * px_, boost::detail::local_counted_base * pn_ ) BOOST_SP_NOEXCEPT : px( px_ ), pn( pn_ )
+ {
+ }
+
+ template<class Y>
+ explicit local_shared_ptr( Y * p ): px( p ), pn( 0 )
+ {
+ boost::detail::lsp_pointer_construct( this, p, pn );
+ }
+
+ template<class Y, class D> local_shared_ptr( Y * p, D d ): px( p ), pn( 0 )
+ {
+ boost::detail::lsp_deleter_construct( this, p, d, pn );
+ }
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+ template<class D> local_shared_ptr( boost::detail::sp_nullptr_t p, D d ): px( p ), pn( 0 )
+ {
+ boost::detail::lsp_deleter_construct( this, p, d, pn );
+ }
+
+#endif
+
+ template<class Y, class D, class A> local_shared_ptr( Y * p, D d, A a ): px( p ), pn( 0 )
+ {
+ boost::detail::lsp_allocator_construct( this, p, d, a, pn );
+ }
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+ template<class D, class A> local_shared_ptr( boost::detail::sp_nullptr_t p, D d, A a ): px( p ), pn( 0 )
+ {
+ boost::detail::lsp_allocator_construct( this, p, d, a, pn );
+ }
+
+#endif
+
+ // construction from shared_ptr
+
+ template<class Y> local_shared_ptr( shared_ptr<Y> const & r,
+ typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty() )
+ : px( r.get() ), pn( 0 )
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ if( r.use_count() != 0 )
+ {
+ pn = new boost::detail::local_counted_impl( r._internal_count() );
+ }
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y> local_shared_ptr( shared_ptr<Y> && r,
+ typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty() )
+ : px( r.get() ), pn( 0 )
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ if( r.use_count() != 0 )
+ {
+ pn = new boost::detail::local_counted_impl( r._internal_count() );
+ r.reset();
+ }
+ }
+
+#endif
+
+ // construction from unique_ptr
+
+#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template< class Y, class D >
+ local_shared_ptr( std::unique_ptr< Y, D > && r,
+ typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty() )
+ : px( r.get() ), pn( 0 )
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ if( px )
+ {
+ pn = new boost::detail::local_counted_impl( shared_ptr<T>( std::move(r) )._internal_count() );
+ }
+ }
+
+#endif
+
+ template< class Y, class D >
+ local_shared_ptr( boost::movelib::unique_ptr< Y, D > r ); // !
+ // : px( r.get() ), pn( new boost::detail::local_counted_impl( shared_ptr<T>( std::move(r) ) ) )
+ //{
+ // boost::detail::sp_assert_convertible< Y, T >();
+ //}
+
+ // copy constructor
+
+ local_shared_ptr( local_shared_ptr const & r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
+ {
+ if( pn )
+ {
+ pn->add_ref();
+ }
+ }
+
+ // move constructor
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ local_shared_ptr( local_shared_ptr && r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
+ {
+ r.px = 0;
+ r.pn = 0;
+ }
+
+#endif
+
+ // converting copy constructor
+
+ template<class Y> local_shared_ptr( local_shared_ptr<Y> const & r,
+ typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty() ) BOOST_SP_NOEXCEPT
+ : px( r.px ), pn( r.pn )
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ if( pn )
+ {
+ pn->add_ref();
+ }
+ }
+
+ // converting move constructor
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y> local_shared_ptr( local_shared_ptr<Y> && r,
+ typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty() ) BOOST_SP_NOEXCEPT
+ : px( r.px ), pn( r.pn )
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ r.px = 0;
+ r.pn = 0;
+ }
+
+#endif
+
+ // aliasing
+
+ template<class Y>
+ local_shared_ptr( local_shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn( r.pn )
+ {
+ if( pn )
+ {
+ pn->add_ref();
+ }
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y>
+ local_shared_ptr( local_shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn( r.pn )
+ {
+ r.px = 0;
+ r.pn = 0;
+ }
+
+#endif
+
+ // assignment
+
+ local_shared_ptr & operator=( local_shared_ptr const & r ) BOOST_SP_NOEXCEPT
+ {
+ local_shared_ptr( r ).swap( *this );
+ return *this;
+ }
+
+ template<class Y> local_shared_ptr & operator=( local_shared_ptr<Y> const & r ) BOOST_SP_NOEXCEPT
+ {
+ local_shared_ptr( r ).swap( *this );
+ return *this;
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ local_shared_ptr & operator=( local_shared_ptr && r ) BOOST_SP_NOEXCEPT
+ {
+ local_shared_ptr( std::move( r ) ).swap( *this );
+ return *this;
+ }
+
+ template<class Y>
+ local_shared_ptr & operator=( local_shared_ptr<Y> && r ) BOOST_SP_NOEXCEPT
+ {
+ local_shared_ptr( std::move( r ) ).swap( *this );
+ return *this;
+ }
+
+#endif
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+ local_shared_ptr & operator=( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
+ {
+ local_shared_ptr().swap(*this);
+ return *this;
+ }
+
+#endif
+
+#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y, class D>
+ local_shared_ptr & operator=( std::unique_ptr<Y, D> && r )
+ {
+ local_shared_ptr( std::move(r) ).swap( *this );
+ return *this;
+ }
+
+#endif
+
+ template<class Y, class D>
+ local_shared_ptr & operator=( boost::movelib::unique_ptr<Y, D> r ); // !
+
+ // reset
+
+ void reset() BOOST_SP_NOEXCEPT
+ {
+ local_shared_ptr().swap( *this );
+ }
+
+ template<class Y> void reset( Y * p ) // Y must be complete
+ {
+ local_shared_ptr( p ).swap( *this );
+ }
+
+ template<class Y, class D> void reset( Y * p, D d )
+ {
+ local_shared_ptr( p, d ).swap( *this );
+ }
+
+ template<class Y, class D, class A> void reset( Y * p, D d, A a )
+ {
+ local_shared_ptr( p, d, a ).swap( *this );
+ }
+
+ template<class Y> void reset( local_shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT
+ {
+ local_shared_ptr( r, p ).swap( *this );
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y> void reset( local_shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPT
+ {
+ local_shared_ptr( std::move( r ), p ).swap( *this );
+ }
+
+#endif
+
+ // accessors
+
+ typename boost::detail::sp_dereference< T >::type operator* () const BOOST_SP_NOEXCEPT
+ {
+ return *px;
+ }
+
+ typename boost::detail::sp_member_access< T >::type operator-> () const BOOST_SP_NOEXCEPT
+ {
+ return px;
+ }
+
+ typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const BOOST_SP_NOEXCEPT_WITH_ASSERT
+ {
+ BOOST_ASSERT( px != 0 );
+ BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) );
+
+ return static_cast< typename boost::detail::sp_array_access< T >::type >( px[ i ] );
+ }
+
+ element_type * get() const BOOST_SP_NOEXCEPT
+ {
+ return px;
+ }
+
+ // implicit conversion to "bool"
+#include <boost/smart_ptr/detail/operator_bool.hpp>
+
+ long local_use_count() const BOOST_SP_NOEXCEPT
+ {
+ return pn? pn->local_use_count(): 0;
+ }
+
+ // conversions to shared_ptr, weak_ptr
+
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
+ template<class Y, class E = typename boost::detail::sp_enable_if_convertible<T,Y>::type> operator shared_ptr<Y>() const BOOST_SP_NOEXCEPT
+#else
+ template<class Y> operator shared_ptr<Y>() const BOOST_SP_NOEXCEPT
+#endif
+ {
+ boost::detail::sp_assert_convertible<T, Y>();
+
+ if( pn )
+ {
+ return shared_ptr<Y>( boost::detail::sp_internal_constructor_tag(), px, pn->local_cb_get_shared_count() );
+ }
+ else
+ {
+ return shared_ptr<Y>();
+ }
+ }
+
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
+ template<class Y, class E = typename boost::detail::sp_enable_if_convertible<T,Y>::type> operator weak_ptr<Y>() const BOOST_SP_NOEXCEPT
+#else
+ template<class Y> operator weak_ptr<Y>() const BOOST_SP_NOEXCEPT
+#endif
+ {
+ boost::detail::sp_assert_convertible<T, Y>();
+
+ if( pn )
+ {
+ return shared_ptr<Y>( boost::detail::sp_internal_constructor_tag(), px, pn->local_cb_get_shared_count() );
+ }
+ else
+ {
+ return weak_ptr<Y>();
+ }
+ }
+
+ // swap
+
+ void swap( local_shared_ptr & r ) BOOST_SP_NOEXCEPT
+ {
+ std::swap( px, r.px );
+ std::swap( pn, r.pn );
+ }
+
+ // owner_before
+
+ template<class Y> bool owner_before( local_shared_ptr<Y> const & r ) const BOOST_SP_NOEXCEPT
+ {
+ return std::less< boost::detail::local_counted_base* >()( pn, r.pn );
+ }
+};
+
+template<class T, class U> inline bool operator==( local_shared_ptr<T> const & a, local_shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT
+{
+ return a.get() == b.get();
+}
+
+template<class T, class U> inline bool operator!=( local_shared_ptr<T> const & a, local_shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT
+{
+ return a.get() != b.get();
+}
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+template<class T> inline bool operator==( local_shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
+{
+ return p.get() == 0;
+}
+
+template<class T> inline bool operator==( boost::detail::sp_nullptr_t, local_shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return p.get() == 0;
+}
+
+template<class T> inline bool operator!=( local_shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
+{
+ return p.get() != 0;
+}
+
+template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, local_shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return p.get() != 0;
+}
+
+#endif
+
+template<class T, class U> inline bool operator==( local_shared_ptr<T> const & a, shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT
+{
+ return a.get() == b.get();
+}
+
+template<class T, class U> inline bool operator!=( local_shared_ptr<T> const & a, shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT
+{
+ return a.get() != b.get();
+}
+
+template<class T, class U> inline bool operator==( shared_ptr<T> const & a, local_shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT
+{
+ return a.get() == b.get();
+}
+
+template<class T, class U> inline bool operator!=( shared_ptr<T> const & a, local_shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT
+{
+ return a.get() != b.get();
+}
+
+template<class T, class U> inline bool operator<(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) BOOST_SP_NOEXCEPT
+{
+ return a.owner_before( b );
+}
+
+template<class T> inline void swap( local_shared_ptr<T> & a, local_shared_ptr<T> & b ) BOOST_SP_NOEXCEPT
+{
+ a.swap( b );
+}
+
+template<class T, class U> local_shared_ptr<T> static_pointer_cast( local_shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
+{
+ (void) static_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename local_shared_ptr<T>::element_type E;
+
+ E * p = static_cast< E* >( r.get() );
+ return local_shared_ptr<T>( r, p );
+}
+
+template<class T, class U> local_shared_ptr<T> const_pointer_cast( local_shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
+{
+ (void) const_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename local_shared_ptr<T>::element_type E;
+
+ E * p = const_cast< E* >( r.get() );
+ return local_shared_ptr<T>( r, p );
+}
+
+template<class T, class U> local_shared_ptr<T> dynamic_pointer_cast( local_shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
+{
+ (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename local_shared_ptr<T>::element_type E;
+
+ E * p = dynamic_cast< E* >( r.get() );
+ return p? local_shared_ptr<T>( r, p ): local_shared_ptr<T>();
+}
+
+template<class T, class U> local_shared_ptr<T> reinterpret_pointer_cast( local_shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
+{
+ (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename local_shared_ptr<T>::element_type E;
+
+ E * p = reinterpret_cast< E* >( r.get() );
+ return local_shared_ptr<T>( r, p );
+}
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+template<class T, class U> local_shared_ptr<T> static_pointer_cast( local_shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
+{
+ (void) static_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename local_shared_ptr<T>::element_type E;
+
+ E * p = static_cast< E* >( r.get() );
+ return local_shared_ptr<T>( std::move(r), p );
+}
+
+template<class T, class U> local_shared_ptr<T> const_pointer_cast( local_shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
+{
+ (void) const_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename local_shared_ptr<T>::element_type E;
+
+ E * p = const_cast< E* >( r.get() );
+ return local_shared_ptr<T>( std::move(r), p );
+}
+
+template<class T, class U> local_shared_ptr<T> dynamic_pointer_cast( local_shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
+{
+ (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename local_shared_ptr<T>::element_type E;
+
+ E * p = dynamic_cast< E* >( r.get() );
+ return p? local_shared_ptr<T>( std::move(r), p ): local_shared_ptr<T>();
+}
+
+template<class T, class U> local_shared_ptr<T> reinterpret_pointer_cast( local_shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
+{
+ (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename local_shared_ptr<T>::element_type E;
+
+ E * p = reinterpret_cast< E* >( r.get() );
+ return local_shared_ptr<T>( std::move(r), p );
+}
+
+#endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+// get_pointer() enables boost::mem_fn to recognize local_shared_ptr
+
+template<class T> inline typename local_shared_ptr<T>::element_type * get_pointer( local_shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return p.get();
+}
+
+// operator<<
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< ( std::basic_ostream<E, T> & os, local_shared_ptr<Y> const & p )
+{
+ os << p.get();
+ return os;
+}
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+// get_deleter
+
+template<class D, class T> D * get_deleter( local_shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return get_deleter<D>( shared_ptr<T>( p ) );
+}
+
+// hash_value
+
+template< class T > struct hash;
+
+template< class T > std::size_t hash_value( local_shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return boost::hash< typename local_shared_ptr<T>::element_type* >()( p.get() );
+}
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_LOCAL_SHARED_PTR_HPP_INCLUDED
diff --git a/boost/smart_ptr/make_local_shared.hpp b/boost/smart_ptr/make_local_shared.hpp
new file mode 100644
index 0000000000..23114fea26
--- /dev/null
+++ b/boost/smart_ptr/make_local_shared.hpp
@@ -0,0 +1,17 @@
+#ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_HPP_INCLUDED
+#define BOOST_SMART_PTR_MAKE_LOCAL_SHARED_HPP_INCLUDED
+
+// make_local_shared.hpp
+//
+// 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
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+
+#include <boost/smart_ptr/make_local_shared_object.hpp>
+#include <boost/smart_ptr/make_local_shared_array.hpp>
+
+#endif // #ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_HPP_INCLUDED
diff --git a/boost/smart_ptr/make_local_shared_array.hpp b/boost/smart_ptr/make_local_shared_array.hpp
new file mode 100644
index 0000000000..663f83479b
--- /dev/null
+++ b/boost/smart_ptr/make_local_shared_array.hpp
@@ -0,0 +1,67 @@
+/*
+Copyright 2017 Peter Dimov
+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)
+*/
+#ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_ARRAY_HPP
+#define BOOST_SMART_PTR_MAKE_LOCAL_SHARED_ARRAY_HPP
+
+#include <boost/smart_ptr/allocate_local_shared_array.hpp>
+
+namespace boost {
+
+template<class T>
+inline typename detail::lsp_if_size_array<T>::type
+make_local_shared()
+{
+ return boost::allocate_local_shared<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>());
+}
+
+template<class T>
+inline typename detail::lsp_if_size_array<T>::type
+make_local_shared(const typename detail::sp_array_element<T>::type& value)
+{
+ return boost::allocate_local_shared<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>(), value);
+}
+
+template<class T>
+inline typename detail::lsp_if_array<T>::type
+make_local_shared(std::size_t size)
+{
+ return boost::allocate_local_shared<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>(), size);
+}
+
+template<class T>
+inline typename detail::lsp_if_array<T>::type
+make_local_shared(std::size_t size,
+ const typename detail::sp_array_element<T>::type& value)
+{
+ return boost::allocate_local_shared<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>(), size, value);
+}
+
+template<class T>
+inline typename detail::lsp_if_size_array<T>::type
+make_local_shared_noinit()
+{
+ return allocate_local_shared_noinit<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>());
+}
+
+template<class T>
+inline typename detail::lsp_if_array<T>::type
+make_local_shared_noinit(std::size_t size)
+{
+ return allocate_local_shared_noinit<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>(), size);
+}
+
+} /* boost */
+
+#endif
diff --git a/boost/smart_ptr/make_local_shared_object.hpp b/boost/smart_ptr/make_local_shared_object.hpp
new file mode 100644
index 0000000000..ab83d60e61
--- /dev/null
+++ b/boost/smart_ptr/make_local_shared_object.hpp
@@ -0,0 +1,199 @@
+#ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_OBJECT_HPP_INCLUDED
+#define BOOST_SMART_PTR_MAKE_LOCAL_SHARED_OBJECT_HPP_INCLUDED
+
+// make_local_shared_object.hpp
+//
+// 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
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+
+#include <boost/smart_ptr/local_shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/config.hpp>
+#include <utility>
+#include <cstddef>
+
+namespace boost
+{
+
+namespace detail
+{
+
+// lsp_if_not_array
+
+template<class T> struct lsp_if_not_array
+{
+ typedef boost::local_shared_ptr<T> type;
+};
+
+template<class T> struct lsp_if_not_array<T[]>
+{
+};
+
+template<class T, std::size_t N> struct lsp_if_not_array<T[N]>
+{
+};
+
+// lsp_ms_deleter
+
+template<class T, class A> class lsp_ms_deleter: public local_counted_impl_em
+{
+private:
+
+ typedef typename sp_aligned_storage<sizeof(T), ::boost::alignment_of<T>::value>::type storage_type;
+
+ storage_type storage_;
+ A a_;
+ bool initialized_;
+
+private:
+
+ void destroy() BOOST_SP_NOEXCEPT
+ {
+ if( initialized_ )
+ {
+ T * p = reinterpret_cast< T* >( storage_.data_ );
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ std::allocator_traits<A>::destroy( a_, p );
+
+#else
+
+ p->~T();
+
+#endif
+
+ initialized_ = false;
+ }
+ }
+
+public:
+
+ explicit lsp_ms_deleter( A const & a ) BOOST_SP_NOEXCEPT : a_( a ), initialized_( false )
+ {
+ }
+
+ // optimization: do not copy storage_
+ lsp_ms_deleter( lsp_ms_deleter const & r ) BOOST_SP_NOEXCEPT : a_( r.a_), initialized_( false )
+ {
+ }
+
+ ~lsp_ms_deleter() BOOST_SP_NOEXCEPT
+ {
+ destroy();
+ }
+
+ void operator()( T * ) BOOST_SP_NOEXCEPT
+ {
+ destroy();
+ }
+
+ static void operator_fn( T* ) BOOST_SP_NOEXCEPT // operator() can't be static
+ {
+ }
+
+ void * address() BOOST_SP_NOEXCEPT
+ {
+ return storage_.data_;
+ }
+
+ void set_initialized() BOOST_SP_NOEXCEPT
+ {
+ initialized_ = true;
+ }
+};
+
+} // namespace detail
+
+template<class T, class A, class... Args> typename boost::detail::lsp_if_not_array<T>::type allocate_local_shared( A const & a, Args&&... args )
+{
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ typedef typename std::allocator_traits<A>::template rebind_alloc<T> A2;
+
+#else
+
+ typedef typename A::template rebind<T>::other A2;
+
+#endif
+
+ A2 a2( a );
+
+ typedef boost::detail::lsp_ms_deleter<T, A2> D;
+
+ boost::shared_ptr<T> pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a2 );
+
+ D * pd = static_cast< D* >( pt._internal_get_untyped_deleter() );
+ void * pv = pd->address();
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ std::allocator_traits<A2>::construct( a2, static_cast< T* >( pv ), std::forward<Args>( args )... );
+
+#else
+
+ ::new( pv ) T( std::forward<Args>( args )... );
+
+#endif
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+
+ pd->pn_ = pt._internal_count();
+
+ return boost::local_shared_ptr<T>( boost::detail::lsp_internal_constructor_tag(), pt2, pd );
+}
+
+template<class T, class A> typename boost::detail::lsp_if_not_array<T>::type allocate_local_shared_noinit( A const & a )
+{
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ typedef typename std::allocator_traits<A>::template rebind_alloc<T> A2;
+
+#else
+
+ typedef typename A::template rebind<T>::other A2;
+
+#endif
+
+ A2 a2( a );
+
+ typedef boost::detail::lsp_ms_deleter< T, std::allocator<T> > D;
+
+ boost::shared_ptr<T> pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a2 );
+
+ D * pd = static_cast< D* >( pt._internal_get_untyped_deleter() );
+ void * pv = pd->address();
+
+ ::new( pv ) T;
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+
+ pd->pn_ = pt._internal_count();
+
+ return boost::local_shared_ptr<T>( boost::detail::lsp_internal_constructor_tag(), pt2, pd );
+}
+
+template<class T, class... Args> typename boost::detail::lsp_if_not_array<T>::type make_local_shared( Args&&... args )
+{
+ return boost::allocate_local_shared<T>( std::allocator<T>(), std::forward<Args>(args)... );
+}
+
+template<class T> typename boost::detail::lsp_if_not_array<T>::type make_local_shared_noinit()
+{
+ return boost::allocate_shared_noinit<T>( std::allocator<T>() );
+}
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED
diff --git a/boost/smart_ptr/make_shared.hpp b/boost/smart_ptr/make_shared.hpp
index 8d0e3ea400..dd9191c61d 100644
--- a/boost/smart_ptr/make_shared.hpp
+++ b/boost/smart_ptr/make_shared.hpp
@@ -9,8 +9,7 @@
// 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/make_shared.html
-// for documentation.
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
#include <boost/smart_ptr/make_shared_object.hpp>
diff --git a/boost/smart_ptr/make_shared_object.hpp b/boost/smart_ptr/make_shared_object.hpp
index 3bc78ee9ae..c681602dca 100644
--- a/boost/smart_ptr/make_shared_object.hpp
+++ b/boost/smart_ptr/make_shared_object.hpp
@@ -9,14 +9,14 @@
// 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/make_shared.html
-// for documentation.
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
#include <boost/config.hpp>
#include <boost/move/core.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/detail/sp_forward.hpp>
+#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/type_traits/type_with_alignment.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <cstddef>
@@ -48,7 +48,7 @@ private:
private:
- void destroy()
+ void destroy() BOOST_SP_NOEXCEPT
{
if( initialized_ )
{
@@ -70,39 +70,39 @@ private:
public:
- sp_ms_deleter() BOOST_NOEXCEPT : initialized_( false )
+ sp_ms_deleter() BOOST_SP_NOEXCEPT : initialized_( false )
{
}
- template<class A> explicit sp_ms_deleter( A const & ) BOOST_NOEXCEPT : initialized_( false )
+ template<class A> explicit sp_ms_deleter( A const & ) BOOST_SP_NOEXCEPT : initialized_( false )
{
}
// optimization: do not copy storage_
- sp_ms_deleter( sp_ms_deleter const & ) BOOST_NOEXCEPT : initialized_( false )
+ sp_ms_deleter( sp_ms_deleter const & ) BOOST_SP_NOEXCEPT : initialized_( false )
{
}
- ~sp_ms_deleter()
+ ~sp_ms_deleter() BOOST_SP_NOEXCEPT
{
destroy();
}
- void operator()( T * )
+ void operator()( T * ) BOOST_SP_NOEXCEPT
{
destroy();
}
- static void operator_fn( T* ) // operator() can't be static
+ static void operator_fn( T* ) BOOST_SP_NOEXCEPT // operator() can't be static
{
}
- void * address() BOOST_NOEXCEPT
+ void * address() BOOST_SP_NOEXCEPT
{
return storage_.data_;
}
- void set_initialized() BOOST_NOEXCEPT
+ void set_initialized() BOOST_SP_NOEXCEPT
{
initialized_ = true;
}
@@ -120,7 +120,7 @@ private:
private:
- void destroy()
+ void destroy() BOOST_SP_NOEXCEPT
{
if( initialized_ )
{
@@ -142,35 +142,35 @@ private:
public:
- sp_as_deleter( A const & a ) BOOST_NOEXCEPT : a_( a ), initialized_( false )
+ sp_as_deleter( A const & a ) BOOST_SP_NOEXCEPT : a_( a ), initialized_( false )
{
}
// optimization: do not copy storage_
- sp_as_deleter( sp_as_deleter const & r ) BOOST_NOEXCEPT : a_( r.a_), initialized_( false )
+ sp_as_deleter( sp_as_deleter const & r ) BOOST_SP_NOEXCEPT : a_( r.a_), initialized_( false )
{
}
- ~sp_as_deleter()
+ ~sp_as_deleter() BOOST_SP_NOEXCEPT
{
destroy();
}
- void operator()( T * )
+ void operator()( T * ) BOOST_SP_NOEXCEPT
{
destroy();
}
- static void operator_fn( T* ) // operator() can't be static
+ static void operator_fn( T* ) BOOST_SP_NOEXCEPT // operator() can't be static
{
}
- void * address() BOOST_NOEXCEPT
+ void * address() BOOST_SP_NOEXCEPT
{
return storage_.data_;
}
- void set_initialized() BOOST_NOEXCEPT
+ void set_initialized() BOOST_SP_NOEXCEPT
{
initialized_ = true;
}
diff --git a/boost/smart_ptr/owner_less.hpp b/boost/smart_ptr/owner_less.hpp
index 75d182c121..5f50aeb5b8 100644
--- a/boost/smart_ptr/owner_less.hpp
+++ b/boost/smart_ptr/owner_less.hpp
@@ -11,7 +11,7 @@
// 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/smart_ptr.htm for documentation.
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
//
namespace boost
diff --git a/boost/smart_ptr/scoped_array.hpp b/boost/smart_ptr/scoped_array.hpp
index f847c094e4..05dd05aea8 100644
--- a/boost/smart_ptr/scoped_array.hpp
+++ b/boost/smart_ptr/scoped_array.hpp
@@ -8,8 +8,7 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
-// http://www.boost.org/libs/smart_ptr/scoped_array.htm
-//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
#include <boost/config.hpp>
#include <boost/assert.hpp>
@@ -62,7 +61,7 @@ public:
#endif
}
- ~scoped_array() // never throws
+ ~scoped_array() BOOST_SP_NOEXCEPT
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_array_destructor_hook( px );
@@ -70,20 +69,20 @@ public:
boost::checked_array_delete( px );
}
- void reset(T * p = 0) // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
+ 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 // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
+ 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_NOEXCEPT
+ T * get() const BOOST_SP_NOEXCEPT
{
return px;
}
@@ -91,7 +90,7 @@ public:
// implicit conversion to "bool"
#include <boost/smart_ptr/detail/operator_bool.hpp>
- void swap(scoped_array & b) BOOST_NOEXCEPT
+ void swap(scoped_array & b) BOOST_SP_NOEXCEPT
{
T * tmp = b.px;
b.px = px;
@@ -101,29 +100,29 @@ public:
#if !defined( BOOST_NO_CXX11_NULLPTR )
-template<class T> inline bool operator==( scoped_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
+template<class T> inline bool operator==( scoped_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
{
return p.get() == 0;
}
-template<class T> inline bool operator==( boost::detail::sp_nullptr_t, scoped_array<T> const & p ) BOOST_NOEXCEPT
+template<class T> inline bool operator==( boost::detail::sp_nullptr_t, scoped_array<T> const & p ) BOOST_SP_NOEXCEPT
{
return p.get() == 0;
}
-template<class T> inline bool operator!=( scoped_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
+template<class T> inline bool operator!=( scoped_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
{
return p.get() != 0;
}
-template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, scoped_array<T> const & p ) BOOST_NOEXCEPT
+template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, scoped_array<T> const & p ) BOOST_SP_NOEXCEPT
{
return p.get() != 0;
}
#endif
-template<class T> inline void swap(scoped_array<T> & a, scoped_array<T> & b) BOOST_NOEXCEPT
+template<class T> inline void swap(scoped_array<T> & a, scoped_array<T> & b) BOOST_SP_NOEXCEPT
{
a.swap(b);
}
diff --git a/boost/smart_ptr/scoped_ptr.hpp b/boost/smart_ptr/scoped_ptr.hpp
index 8fd8a180fb..5325eba5ff 100644
--- a/boost/smart_ptr/scoped_ptr.hpp
+++ b/boost/smart_ptr/scoped_ptr.hpp
@@ -8,8 +8,7 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
-// http://www.boost.org/libs/smart_ptr/scoped_ptr.htm
-//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
#include <boost/config.hpp>
#include <boost/assert.hpp>
@@ -63,7 +62,7 @@ public:
typedef T element_type;
- explicit scoped_ptr( T * p = 0 ) BOOST_SP_NOEXCEPT : px( p ) // never throws
+ explicit scoped_ptr( T * p = 0 ) BOOST_SP_NOEXCEPT : px( p )
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_scalar_constructor_hook( px );
@@ -72,7 +71,7 @@ public:
#ifndef BOOST_NO_AUTO_PTR
- explicit scoped_ptr( std::auto_ptr<T> p ) BOOST_NOEXCEPT : px( p.release() )
+ explicit scoped_ptr( std::auto_ptr<T> p ) BOOST_SP_NOEXCEPT : px( p.release() )
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_scalar_constructor_hook( px );
@@ -81,7 +80,7 @@ public:
#endif
- ~scoped_ptr() // never throws
+ ~scoped_ptr() BOOST_SP_NOEXCEPT
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_scalar_destructor_hook( px );
@@ -89,25 +88,25 @@ public:
boost::checked_delete( px );
}
- void reset(T * p = 0) // never throws
+ 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 // never throws
+ T & operator*() const BOOST_SP_NOEXCEPT_WITH_ASSERT
{
BOOST_ASSERT( px != 0 );
return *px;
}
- T * operator->() const // never throws
+ T * operator->() const BOOST_SP_NOEXCEPT_WITH_ASSERT
{
BOOST_ASSERT( px != 0 );
return px;
}
- T * get() const BOOST_NOEXCEPT
+ T * get() const BOOST_SP_NOEXCEPT
{
return px;
}
@@ -115,7 +114,7 @@ public:
// implicit conversion to "bool"
#include <boost/smart_ptr/detail/operator_bool.hpp>
- void swap(scoped_ptr & b) BOOST_NOEXCEPT
+ void swap(scoped_ptr & b) BOOST_SP_NOEXCEPT
{
T * tmp = b.px;
b.px = px;
@@ -125,36 +124,36 @@ public:
#if !defined( BOOST_NO_CXX11_NULLPTR )
-template<class T> inline bool operator==( scoped_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
+template<class T> inline bool operator==( scoped_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
{
return p.get() == 0;
}
-template<class T> inline bool operator==( boost::detail::sp_nullptr_t, scoped_ptr<T> const & p ) BOOST_NOEXCEPT
+template<class T> inline bool operator==( boost::detail::sp_nullptr_t, scoped_ptr<T> const & p ) BOOST_SP_NOEXCEPT
{
return p.get() == 0;
}
-template<class T> inline bool operator!=( scoped_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
+template<class T> inline bool operator!=( scoped_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
{
return p.get() != 0;
}
-template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, scoped_ptr<T> const & p ) BOOST_NOEXCEPT
+template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, scoped_ptr<T> const & p ) BOOST_SP_NOEXCEPT
{
return p.get() != 0;
}
#endif
-template<class T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) BOOST_NOEXCEPT
+template<class T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) BOOST_SP_NOEXCEPT
{
a.swap(b);
}
// get_pointer(p) is a generic way to say p.get()
-template<class T> inline T * get_pointer(scoped_ptr<T> const & p) BOOST_NOEXCEPT
+template<class T> inline T * get_pointer(scoped_ptr<T> const & p) BOOST_SP_NOEXCEPT
{
return p.get();
}
diff --git a/boost/smart_ptr/shared_array.hpp b/boost/smart_ptr/shared_array.hpp
index 2e5cb134a3..3ffa7426c3 100644
--- a/boost/smart_ptr/shared_array.hpp
+++ b/boost/smart_ptr/shared_array.hpp
@@ -11,7 +11,7 @@
// 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/shared_array.htm for documentation.
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
//
#include <boost/config.hpp> // for broken compiler workarounds
@@ -120,7 +120,7 @@ public:
shared_array( shared_array<Y> const & r )
#endif
- BOOST_NOEXCEPT : px( r.px ), pn( r.pn ) // never throws
+ BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
{
boost::detail::sp_assert_convertible< Y[], T[] >();
}
@@ -128,7 +128,7 @@ public:
// aliasing
template< class Y >
- shared_array( shared_array<Y> const & r, element_type * p ) BOOST_NOEXCEPT : px( p ), pn( r.pn )
+ shared_array( shared_array<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn( r.pn )
{
}
@@ -143,7 +143,7 @@ public:
#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400)
template<class Y>
- shared_array & operator=( shared_array<Y> const & r ) BOOST_NOEXCEPT
+ shared_array & operator=( shared_array<Y> const & r ) BOOST_SP_NOEXCEPT
{
this_type( r ).swap( *this );
return *this;
@@ -160,7 +160,7 @@ public:
}
template<class Y>
- shared_array & operator=( shared_array<Y> && r ) BOOST_NOEXCEPT
+ shared_array & operator=( shared_array<Y> && r ) BOOST_SP_NOEXCEPT
{
this_type( static_cast< shared_array<Y> && >( r ) ).swap( *this );
return *this;
@@ -168,7 +168,7 @@ public:
#endif
- void reset() BOOST_NOEXCEPT
+ void reset() BOOST_SP_NOEXCEPT
{
this_type().swap( *this );
}
@@ -189,19 +189,19 @@ public:
this_type( p, d, a ).swap( *this );
}
- template<class Y> void reset( shared_array<Y> const & r, element_type * p )
+ template<class Y> void reset( shared_array<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT
{
this_type( r, p ).swap( *this );
}
- T & operator[] (std::ptrdiff_t i) const // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
+ 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_NOEXCEPT
+ T * get() const BOOST_SP_NOEXCEPT
{
return px;
}
@@ -209,23 +209,23 @@ public:
// implicit conversion to "bool"
#include <boost/smart_ptr/detail/operator_bool.hpp>
- bool unique() const BOOST_NOEXCEPT
+ bool unique() const BOOST_SP_NOEXCEPT
{
return pn.unique();
}
- long use_count() const BOOST_NOEXCEPT
+ long use_count() const BOOST_SP_NOEXCEPT
{
return pn.use_count();
}
- void swap(shared_array<T> & other) BOOST_NOEXCEPT
+ void swap(shared_array<T> & other) BOOST_SP_NOEXCEPT
{
std::swap(px, other.px);
pn.swap(other.pn);
}
- void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const
+ void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_SP_NOEXCEPT
{
return pn.get_deleter( ti );
}
@@ -239,51 +239,51 @@ private:
}; // shared_array
-template<class T> inline bool operator==(shared_array<T> const & a, shared_array<T> const & b) BOOST_NOEXCEPT
+template<class T> inline bool operator==(shared_array<T> const & a, shared_array<T> const & b) BOOST_SP_NOEXCEPT
{
return a.get() == b.get();
}
-template<class T> inline bool operator!=(shared_array<T> const & a, shared_array<T> const & b) BOOST_NOEXCEPT
+template<class T> inline bool operator!=(shared_array<T> const & a, shared_array<T> const & b) BOOST_SP_NOEXCEPT
{
return a.get() != b.get();
}
#if !defined( BOOST_NO_CXX11_NULLPTR )
-template<class T> inline bool operator==( shared_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
+template<class T> inline bool operator==( shared_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
{
return p.get() == 0;
}
-template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_array<T> const & p ) BOOST_NOEXCEPT
+template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_array<T> const & p ) BOOST_SP_NOEXCEPT
{
return p.get() == 0;
}
-template<class T> inline bool operator!=( shared_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
+template<class T> inline bool operator!=( shared_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
{
return p.get() != 0;
}
-template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_array<T> const & p ) BOOST_NOEXCEPT
+template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_array<T> const & p ) BOOST_SP_NOEXCEPT
{
return p.get() != 0;
}
#endif
-template<class T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b) BOOST_NOEXCEPT
+template<class T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b) BOOST_SP_NOEXCEPT
{
return std::less<T*>()(a.get(), b.get());
}
-template<class T> void swap(shared_array<T> & a, shared_array<T> & b) BOOST_NOEXCEPT
+template<class T> void swap(shared_array<T> & a, shared_array<T> & b) BOOST_SP_NOEXCEPT
{
a.swap(b);
}
-template< class D, class T > D * get_deleter( shared_array<T> const & p )
+template< class D, class T > D * get_deleter( shared_array<T> const & p ) BOOST_SP_NOEXCEPT
{
return static_cast< D * >( p._internal_get_deleter( BOOST_SP_TYPEID(D) ) );
}
diff --git a/boost/smart_ptr/shared_ptr.hpp b/boost/smart_ptr/shared_ptr.hpp
index e33707b3bc..e8a302c74a 100644
--- a/boost/smart_ptr/shared_ptr.hpp
+++ b/boost/smart_ptr/shared_ptr.hpp
@@ -11,7 +11,7 @@
// 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/shared_ptr.htm for documentation.
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
//
#include <boost/config.hpp> // for broken compiler workarounds
@@ -262,7 +262,7 @@ template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R
// sp_assert_convertible
-template< class Y, class T > inline void sp_assert_convertible()
+template< class Y, class T > inline void sp_assert_convertible() BOOST_SP_NOEXCEPT
{
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
@@ -323,6 +323,10 @@ template< class T, std::size_t N, class Y > inline void sp_deleter_construct( bo
#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+struct sp_internal_constructor_tag
+{
+};
+
} // namespace detail
@@ -345,13 +349,25 @@ public:
typedef typename boost::detail::sp_element< T >::type element_type;
- shared_ptr() BOOST_SP_NOEXCEPT : px( 0 ), pn() // never throws in 1.30+
+ BOOST_CONSTEXPR shared_ptr() BOOST_SP_NOEXCEPT : px( 0 ), pn()
{
}
#if !defined( BOOST_NO_CXX11_NULLPTR )
- shared_ptr( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT : px( 0 ), pn() // never throws
+ BOOST_CONSTEXPR shared_ptr( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT : px( 0 ), pn()
+ {
+ }
+
+#endif
+
+ BOOST_CONSTEXPR shared_ptr( boost::detail::sp_internal_constructor_tag, element_type * px_, boost::detail::shared_count const & pn_ ) BOOST_SP_NOEXCEPT : px( px_ ), pn( pn_ )
+ {
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ BOOST_CONSTEXPR shared_ptr( boost::detail::sp_internal_constructor_tag, element_type * px_, boost::detail::shared_count && pn_ ) BOOST_SP_NOEXCEPT : px( px_ ), pn( std::move( pn_ ) )
{
}
@@ -420,7 +436,7 @@ public:
template<class Y>
shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag )
- BOOST_NOEXCEPT : px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() )
+ BOOST_SP_NOEXCEPT : px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() )
{
if( !pn.empty() )
{
@@ -438,14 +454,14 @@ public:
shared_ptr( shared_ptr<Y> const & r )
#endif
- BOOST_NOEXCEPT : px( r.px ), pn( r.pn )
+ BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
{
boost::detail::sp_assert_convertible< Y, T >();
}
// aliasing
template< class Y >
- shared_ptr( shared_ptr<Y> const & r, element_type * p ) BOOST_NOEXCEPT : px( p ), pn( r.pn )
+ shared_ptr( shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn( r.pn )
{
}
@@ -502,9 +518,12 @@ public:
boost::detail::sp_assert_convertible< Y, T >();
typename std::unique_ptr< Y, D >::pointer tmp = r.get();
- pn = boost::detail::shared_count( r );
- boost::detail::sp_deleter_construct( this, tmp );
+ if( tmp != 0 )
+ {
+ pn = boost::detail::shared_count( r );
+ boost::detail::sp_deleter_construct( this, tmp );
+ }
}
#endif
@@ -515,9 +534,12 @@ public:
boost::detail::sp_assert_convertible< Y, T >();
typename boost::movelib::unique_ptr< Y, D >::pointer tmp = r.get();
- pn = boost::detail::shared_count( r );
- boost::detail::sp_deleter_construct( this, tmp );
+ if( tmp != 0 )
+ {
+ pn = boost::detail::shared_count( r );
+ boost::detail::sp_deleter_construct( this, tmp );
+ }
}
// assignment
@@ -531,7 +553,7 @@ public:
#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400)
template<class Y>
- shared_ptr & operator=(shared_ptr<Y> const & r) BOOST_NOEXCEPT
+ shared_ptr & operator=(shared_ptr<Y> const & r) BOOST_SP_NOEXCEPT
{
this_type(r).swap(*this);
return *this;
@@ -592,10 +614,13 @@ public:
shared_ptr tmp;
- tmp.px = p;
- tmp.pn = boost::detail::shared_count( r );
+ if( p != 0 )
+ {
+ tmp.px = p;
+ tmp.pn = boost::detail::shared_count( r );
- boost::detail::sp_deleter_construct( &tmp, p );
+ boost::detail::sp_deleter_construct( &tmp, p );
+ }
tmp.swap( *this );
@@ -622,7 +647,7 @@ public:
shared_ptr( shared_ptr<Y> && r )
#endif
- BOOST_NOEXCEPT : px( r.px ), pn()
+ BOOST_SP_NOEXCEPT : px( r.px ), pn()
{
boost::detail::sp_assert_convertible< Y, T >();
@@ -637,7 +662,7 @@ public:
}
template<class Y>
- shared_ptr & operator=( shared_ptr<Y> && r ) BOOST_NOEXCEPT
+ shared_ptr & operator=( shared_ptr<Y> && r ) BOOST_SP_NOEXCEPT
{
this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this );
return *this;
@@ -645,7 +670,7 @@ public:
// aliasing move
template<class Y>
- shared_ptr( shared_ptr<Y> && r, element_type * p ) BOOST_NOEXCEPT : px( p ), pn()
+ shared_ptr( shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn()
{
pn.swap( r.pn );
r.px = 0;
@@ -655,7 +680,7 @@ public:
#if !defined( BOOST_NO_CXX11_NULLPTR )
- shared_ptr & operator=( boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT // never throws
+ shared_ptr & operator=( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
{
this_type().swap(*this);
return *this;
@@ -663,7 +688,7 @@ public:
#endif
- void reset() BOOST_NOEXCEPT // never throws in 1.30+
+ void reset() BOOST_SP_NOEXCEPT
{
this_type().swap(*this);
}
@@ -684,36 +709,33 @@ public:
this_type( p, d, a ).swap( *this );
}
- template<class Y> void reset( shared_ptr<Y> const & r, element_type * p )
+ template<class Y> void reset( shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT
{
this_type( r, p ).swap( *this );
}
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
- template<class Y> void reset( shared_ptr<Y> && r, element_type * p )
+ template<class Y> void reset( shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPT
{
this_type( static_cast< shared_ptr<Y> && >( r ), p ).swap( *this );
}
#endif
- // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
- typename boost::detail::sp_dereference< T >::type operator* () const
+ typename boost::detail::sp_dereference< T >::type operator* () const BOOST_SP_NOEXCEPT_WITH_ASSERT
{
BOOST_ASSERT( px != 0 );
return *px;
}
- // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
- typename boost::detail::sp_member_access< T >::type operator-> () const
+ typename boost::detail::sp_member_access< T >::type operator-> () const BOOST_SP_NOEXCEPT_WITH_ASSERT
{
BOOST_ASSERT( px != 0 );
return px;
}
- // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
- typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const
+ typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const BOOST_SP_NOEXCEPT_WITH_ASSERT
{
BOOST_ASSERT( px != 0 );
BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) );
@@ -721,7 +743,7 @@ public:
return static_cast< typename boost::detail::sp_array_access< T >::type >( px[ i ] );
}
- element_type * get() const BOOST_NOEXCEPT
+ element_type * get() const BOOST_SP_NOEXCEPT
{
return px;
}
@@ -729,47 +751,57 @@ public:
// implicit conversion to "bool"
#include <boost/smart_ptr/detail/operator_bool.hpp>
- bool unique() const BOOST_NOEXCEPT
+ bool unique() const BOOST_SP_NOEXCEPT
{
return pn.unique();
}
- long use_count() const BOOST_NOEXCEPT
+ long use_count() const BOOST_SP_NOEXCEPT
{
return pn.use_count();
}
- void swap( shared_ptr & other ) BOOST_NOEXCEPT
+ void swap( shared_ptr & other ) BOOST_SP_NOEXCEPT
{
std::swap(px, other.px);
pn.swap(other.pn);
}
- template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_NOEXCEPT
+ template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT
{
return pn < rhs.pn;
}
- template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_NOEXCEPT
+ template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT
{
return pn < rhs.pn;
}
- void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_NOEXCEPT
+ void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_SP_NOEXCEPT
{
return pn.get_deleter( ti );
}
- void * _internal_get_untyped_deleter() const BOOST_NOEXCEPT
+ void * _internal_get_local_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_SP_NOEXCEPT
+ {
+ return pn.get_local_deleter( ti );
+ }
+
+ void * _internal_get_untyped_deleter() const BOOST_SP_NOEXCEPT
{
return pn.get_untyped_deleter();
}
- bool _internal_equiv( shared_ptr const & r ) const BOOST_NOEXCEPT
+ bool _internal_equiv( shared_ptr const & r ) const BOOST_SP_NOEXCEPT
{
return px == r.px && pn == r.pn;
}
+ boost::detail::shared_count _internal_count() const BOOST_NOEXCEPT
+ {
+ return pn;
+ }
+
// Tasteless as this may seem, making all members public allows member templates
// to work in the absence of member template friends. (Matthew Langston)
@@ -788,12 +820,12 @@ private:
}; // shared_ptr
-template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
+template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_SP_NOEXCEPT
{
return a.get() == b.get();
}
-template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
+template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_SP_NOEXCEPT
{
return a.get() != b.get();
}
@@ -802,7 +834,7 @@ template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, share
// Resolve the ambiguity between our op!= and the one in rel_ops
-template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b) BOOST_NOEXCEPT
+template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b) BOOST_SP_NOEXCEPT
{
return a.get() != b.get();
}
@@ -811,39 +843,39 @@ template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T>
#if !defined( BOOST_NO_CXX11_NULLPTR )
-template<class T> inline bool operator==( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
+template<class T> inline bool operator==( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
{
return p.get() == 0;
}
-template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_NOEXCEPT
+template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
{
return p.get() == 0;
}
-template<class T> inline bool operator!=( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
+template<class T> inline bool operator!=( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
{
return p.get() != 0;
}
-template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_NOEXCEPT
+template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
{
return p.get() != 0;
}
#endif
-template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
+template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_SP_NOEXCEPT
{
return a.owner_before( b );
}
-template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) BOOST_NOEXCEPT
+template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) BOOST_SP_NOEXCEPT
{
a.swap(b);
}
-template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
+template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
{
(void) static_cast< T* >( static_cast< U* >( 0 ) );
@@ -853,7 +885,7 @@ template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> cons
return shared_ptr<T>( r, p );
}
-template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
+template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
{
(void) const_cast< T* >( static_cast< U* >( 0 ) );
@@ -863,7 +895,7 @@ template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> const
return shared_ptr<T>( r, p );
}
-template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
+template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
{
(void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
@@ -873,7 +905,7 @@ template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> con
return p? shared_ptr<T>( r, p ): shared_ptr<T>();
}
-template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
+template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
{
(void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
@@ -885,7 +917,7 @@ template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U>
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
-template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> && r ) BOOST_NOEXCEPT
+template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
{
(void) static_cast< T* >( static_cast< U* >( 0 ) );
@@ -895,7 +927,7 @@ template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> && r
return shared_ptr<T>( std::move(r), p );
}
-template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> && r ) BOOST_NOEXCEPT
+template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
{
(void) const_cast< T* >( static_cast< U* >( 0 ) );
@@ -905,7 +937,7 @@ template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> && r
return shared_ptr<T>( std::move(r), p );
}
-template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> && r ) BOOST_NOEXCEPT
+template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
{
(void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
@@ -915,7 +947,7 @@ template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> &&
return p? shared_ptr<T>( std::move(r), p ): shared_ptr<T>();
}
-template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> && r ) BOOST_NOEXCEPT
+template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
{
(void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
@@ -929,7 +961,7 @@ template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U>
// get_pointer() enables boost::mem_fn to recognize shared_ptr
-template<class T> inline typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p) BOOST_NOEXCEPT
+template<class T> inline typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p) BOOST_SP_NOEXCEPT
{
return p.get();
}
@@ -974,27 +1006,13 @@ template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::
namespace detail
{
-#if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
- ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
- ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )
-
-// g++ 2.9x doesn't allow static_cast<X const *>(void *)
-// apparently EDG 2.38 and HP aCC A.03.35 also don't accept it
-
-template<class D, class T> D * basic_get_deleter(shared_ptr<T> const & p)
-{
- void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D));
- return const_cast<D *>(static_cast<D const *>(q));
-}
-
-#else
-
-template<class D, class T> D * basic_get_deleter( shared_ptr<T> const & p ) BOOST_NOEXCEPT
+template<class D, class T> D * basic_get_deleter( shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
{
return static_cast<D *>( p._internal_get_deleter(BOOST_SP_TYPEID(D)) );
}
-#endif
+template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT;
+template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT;
class esft2_deleter_wrapper
{
@@ -1008,17 +1026,17 @@ public:
{
}
- template< class T > void set_deleter( shared_ptr<T> const & deleter )
+ template< class T > void set_deleter( shared_ptr<T> const & deleter ) BOOST_SP_NOEXCEPT
{
deleter_ = deleter;
}
- template<typename D> D* get_deleter() const BOOST_NOEXCEPT
+ template<typename D> D* get_deleter() const BOOST_SP_NOEXCEPT
{
return boost::detail::basic_get_deleter<D>( deleter_ );
}
- template< class T> void operator()( T* )
+ template< class T> void operator()( T* ) BOOST_SP_NOEXCEPT_WITH_ASSERT
{
BOOST_ASSERT( deleter_.use_count() <= 1 );
deleter_.reset();
@@ -1027,53 +1045,58 @@ public:
} // namespace detail
-template<class D, class T> D * get_deleter( shared_ptr<T> const & p ) BOOST_NOEXCEPT
+template<class D, class T> D * get_deleter( shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
{
- D *del = boost::detail::basic_get_deleter<D>(p);
+ D * d = boost::detail::basic_get_deleter<D>( p );
+
+ if( d == 0 )
+ {
+ d = boost::detail::basic_get_local_deleter( d, p );
+ }
- if(del == 0)
+ if( d == 0 )
{
boost::detail::esft2_deleter_wrapper *del_wrapper = boost::detail::basic_get_deleter<boost::detail::esft2_deleter_wrapper>(p);
// The following get_deleter method call is fully qualified because
// older versions of gcc (2.95, 3.2.3) fail to compile it when written del_wrapper->get_deleter<D>()
- if(del_wrapper) del = del_wrapper->::boost::detail::esft2_deleter_wrapper::get_deleter<D>();
+ if(del_wrapper) d = del_wrapper->::boost::detail::esft2_deleter_wrapper::get_deleter<D>();
}
- return del;
+ return d;
}
// atomic access
#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
-template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ ) BOOST_NOEXCEPT
+template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ ) BOOST_SP_NOEXCEPT
{
return false;
}
-template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p )
+template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p ) BOOST_SP_NOEXCEPT
{
boost::detail::spinlock_pool<2>::scoped_lock lock( p );
return *p;
}
-template<class T> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, /*memory_order mo*/ int )
+template<class T> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, /*memory_order mo*/ int ) BOOST_SP_NOEXCEPT
{
return atomic_load( p );
}
-template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r )
+template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r ) BOOST_SP_NOEXCEPT
{
boost::detail::spinlock_pool<2>::scoped_lock lock( p );
p->swap( r );
}
-template<class T> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ int )
+template<class T> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ int ) BOOST_SP_NOEXCEPT
{
atomic_store( p, r ); // std::move( r )
}
-template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r )
+template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r ) BOOST_SP_NOEXCEPT
{
boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
@@ -1084,12 +1107,12 @@ template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T
return r; // return std::move( r )
}
-template<class T> shared_ptr<T> atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ int )
+template<class T> shared_ptr<T> inline atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ int ) BOOST_SP_NOEXCEPT
{
return atomic_exchange( p, r ); // std::move( r )
}
-template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w )
+template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w ) BOOST_SP_NOEXCEPT
{
boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
@@ -1114,7 +1137,7 @@ template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T>
}
}
-template<class T> inline bool atomic_compare_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, /*memory_order success*/ int, /*memory_order failure*/ int )
+template<class T> inline bool atomic_compare_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, /*memory_order success*/ int, /*memory_order failure*/ int ) BOOST_SP_NOEXCEPT
{
return atomic_compare_exchange( p, v, w ); // std::move( w )
}
@@ -1125,13 +1148,35 @@ template<class T> inline bool atomic_compare_exchange_explicit( shared_ptr<T> *
template< class T > struct hash;
-template< class T > std::size_t hash_value( boost::shared_ptr<T> const & p ) BOOST_NOEXCEPT
+template< class T > std::size_t hash_value( boost::shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
{
return boost::hash< typename boost::shared_ptr<T>::element_type* >()( p.get() );
}
} // namespace boost
+#include <boost/smart_ptr/detail/local_sp_deleter.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID(local_sp_deleter<D>) ) );
+}
+
+template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID(local_sp_deleter<D>) ) );
+}
+
+} // namespace detail
+
+} // namespace boost
+
#if defined( BOOST_SP_DISABLE_DEPRECATED )
#pragma GCC diagnostic pop
#endif
diff --git a/boost/smart_ptr/weak_ptr.hpp b/boost/smart_ptr/weak_ptr.hpp
index f3411f7225..54d9ef3781 100644
--- a/boost/smart_ptr/weak_ptr.hpp
+++ b/boost/smart_ptr/weak_ptr.hpp
@@ -6,11 +6,11 @@
//
// Copyright (c) 2001, 2002, 2003 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)
+// Distributed under the 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/weak_ptr.htm for documentation.
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
//
#include <memory> // boost.TR1 include order fix
@@ -32,7 +32,7 @@ public:
typedef typename boost::detail::sp_element< T >::type element_type;
- weak_ptr() BOOST_SP_NOEXCEPT : px(0), pn() // never throws in 1.30+
+ BOOST_CONSTEXPR weak_ptr() BOOST_SP_NOEXCEPT : px(0), pn()
{
}
@@ -59,7 +59,7 @@ public:
// The "obvious" converting constructor implementation:
//
// template<class Y>
-// weak_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
+// weak_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn)
// {
// }
//
@@ -82,7 +82,7 @@ public:
weak_ptr( weak_ptr<Y> const & r )
#endif
- BOOST_NOEXCEPT : px(r.lock().get()), pn(r.pn)
+ BOOST_SP_NOEXCEPT : px(r.lock().get()), pn(r.pn)
{
boost::detail::sp_assert_convertible< Y, T >();
}
@@ -99,7 +99,7 @@ public:
weak_ptr( weak_ptr<Y> && r )
#endif
- BOOST_NOEXCEPT : px( r.lock().get() ), pn( static_cast< boost::detail::weak_count && >( r.pn ) )
+ BOOST_SP_NOEXCEPT : px( r.lock().get() ), pn( static_cast< boost::detail::weak_count && >( r.pn ) )
{
boost::detail::sp_assert_convertible< Y, T >();
r.px = 0;
@@ -132,7 +132,7 @@ public:
weak_ptr( shared_ptr<Y> const & r )
#endif
- BOOST_NOEXCEPT : px( r.px ), pn( r.pn )
+ BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
{
boost::detail::sp_assert_convertible< Y, T >();
}
@@ -140,7 +140,7 @@ public:
#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)
template<class Y>
- weak_ptr & operator=( weak_ptr<Y> const & r ) BOOST_NOEXCEPT
+ weak_ptr & operator=( weak_ptr<Y> const & r ) BOOST_SP_NOEXCEPT
{
boost::detail::sp_assert_convertible< Y, T >();
@@ -153,7 +153,7 @@ public:
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
template<class Y>
- weak_ptr & operator=( weak_ptr<Y> && r ) BOOST_NOEXCEPT
+ weak_ptr & operator=( weak_ptr<Y> && r ) BOOST_SP_NOEXCEPT
{
this_type( static_cast< weak_ptr<Y> && >( r ) ).swap( *this );
return *this;
@@ -162,7 +162,7 @@ public:
#endif
template<class Y>
- weak_ptr & operator=( shared_ptr<Y> const & r ) BOOST_NOEXCEPT
+ weak_ptr & operator=( shared_ptr<Y> const & r ) BOOST_SP_NOEXCEPT
{
boost::detail::sp_assert_convertible< Y, T >();
@@ -174,50 +174,50 @@ public:
#endif
- shared_ptr<T> lock() const BOOST_NOEXCEPT
+ shared_ptr<T> lock() const BOOST_SP_NOEXCEPT
{
return shared_ptr<T>( *this, boost::detail::sp_nothrow_tag() );
}
- long use_count() const BOOST_NOEXCEPT
+ long use_count() const BOOST_SP_NOEXCEPT
{
return pn.use_count();
}
- bool expired() const BOOST_NOEXCEPT
+ bool expired() const BOOST_SP_NOEXCEPT
{
return pn.use_count() == 0;
}
- bool _empty() const // extension, not in std::weak_ptr
+ bool _empty() const BOOST_SP_NOEXCEPT // extension, not in std::weak_ptr
{
return pn.empty();
}
- void reset() BOOST_NOEXCEPT // never throws in 1.30+
+ void reset() BOOST_SP_NOEXCEPT
{
this_type().swap(*this);
}
- void swap(this_type & other) BOOST_NOEXCEPT
+ void swap(this_type & other) BOOST_SP_NOEXCEPT
{
std::swap(px, other.px);
pn.swap(other.pn);
}
template<typename Y>
- void _internal_aliasing_assign(weak_ptr<Y> const & r, element_type * px2)
+ void _internal_aliasing_assign(weak_ptr<Y> const & r, element_type * px2) BOOST_SP_NOEXCEPT
{
px = px2;
pn = r.pn;
}
- template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_NOEXCEPT
+ template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT
{
return pn < rhs.pn;
}
- template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_NOEXCEPT
+ template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT
{
return pn < rhs.pn;
}
@@ -239,12 +239,12 @@ private:
}; // weak_ptr
-template<class T, class U> inline bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) BOOST_NOEXCEPT
+template<class T, class U> inline bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) BOOST_SP_NOEXCEPT
{
return a.owner_before( b );
}
-template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) BOOST_NOEXCEPT
+template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) BOOST_SP_NOEXCEPT
{
a.swap(b);
}
diff --git a/boost/spirit/home/classic/core/non_terminal/impl/grammar.ipp b/boost/spirit/home/classic/core/non_terminal/impl/grammar.ipp
index 002d221eeb..f5b187d14b 100644
--- a/boost/spirit/home/classic/core/non_terminal/impl/grammar.ipp
+++ b/boost/spirit/home/classic/core/non_terminal/impl/grammar.ipp
@@ -15,7 +15,7 @@
#include <boost/spirit/home/classic/core/non_terminal/impl/object_with_id.ipp>
#include <algorithm>
#include <functional>
-#include <memory> // for std::auto_ptr
+#include <boost/move/unique_ptr.hpp>
#include <boost/weak_ptr.hpp>
#endif
@@ -156,7 +156,7 @@ struct grammar_definition
if (definitions[id]!=0)
return *definitions[id];
- std::auto_ptr<definition_t>
+ boost::movelib::unique_ptr<definition_t>
result(new definition_t(target_grammar->derived()));
#ifdef BOOST_SPIRIT_THREADSAFE
@@ -286,18 +286,10 @@ struct grammar_definition
helper_list_t& helpers =
grammartract_helper_list::do_(self);
-# if defined(BOOST_INTEL_CXX_VERSION)
typedef typename helper_list_t::vector_t::reverse_iterator iterator_t;
for (iterator_t i = helpers.rbegin(); i != helpers.rend(); ++i)
(*i)->undefine(self);
-# else
- typedef impl::grammar_helper_base<GrammarT> helper_base_t;
-
- std::for_each(helpers.rbegin(), helpers.rend(),
- std::bind2nd(std::mem_fun(&helper_base_t::undefine), self));
-# endif
-
#else
(void)self;
#endif
diff --git a/boost/spirit/home/classic/error_handling/exceptions.hpp b/boost/spirit/home/classic/error_handling/exceptions.hpp
index c2e0c86983..0fb036a205 100644
--- a/boost/spirit/home/classic/error_handling/exceptions.hpp
+++ b/boost/spirit/home/classic/error_handling/exceptions.hpp
@@ -140,7 +140,6 @@ BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
parse(ScannerT const& scan) const
{
typedef typename parser_result<ParserT, ScannerT>::type result_t;
- typedef typename ScannerT::iterator_t iterator_t;
result_t hit = this->subject().parse(scan);
if (!hit)
diff --git a/boost/spirit/home/classic/phoenix/special_ops.hpp b/boost/spirit/home/classic/phoenix/special_ops.hpp
index 4a007b23ae..12bf4b70fe 100644
--- a/boost/spirit/home/classic/phoenix/special_ops.hpp
+++ b/boost/spirit/home/classic/phoenix/special_ops.hpp
@@ -30,18 +30,6 @@
#endif
///////////////////////////////////////////////////////////////////////////////
-//#if !defined(PHOENIX_NO_STD_NAMESPACE)
-namespace PHOENIX_STD
-{
-//#endif
-
- template<typename T> class complex;
-
-//#if !defined(PHOENIX_NO_STD_NAMESPACE)
-}
-//#endif
-
-///////////////////////////////////////////////////////////////////////////////
namespace phoenix
{
diff --git a/boost/spirit/home/classic/symbols/impl/tst.ipp b/boost/spirit/home/classic/symbols/impl/tst.ipp
index 1a4a0c1052..60932c94ce 100644
--- a/boost/spirit/home/classic/symbols/impl/tst.ipp
+++ b/boost/spirit/home/classic/symbols/impl/tst.ipp
@@ -10,7 +10,7 @@
#define BOOST_SPIRIT_TST_IPP
///////////////////////////////////////////////////////////////////////////////
-#include <memory> // for std::auto_ptr
+#include <boost/move/unique_ptr.hpp>
#include <boost/spirit/home/classic/core/assert.hpp>
///////////////////////////////////////////////////////////////////////////////
@@ -62,7 +62,7 @@ BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
tst_node*
clone() const
{
- std::auto_ptr<tst_node> copy(new tst_node(value));
+ boost::movelib::unique_ptr<tst_node> copy(new tst_node(value));
if (left)
copy->left = left->clone();
@@ -75,7 +75,7 @@ BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
}
else
{
- std::auto_ptr<T> mid_data(new T(*middle.data));
+ boost::movelib::unique_ptr<T> mid_data(new T(*middle.data));
copy->middle.data = mid_data.release();
}
diff --git a/boost/spirit/home/karma/auxiliary/lazy.hpp b/boost/spirit/home/karma/auxiliary/lazy.hpp
index 32d55fa49a..49cdf12d81 100644
--- a/boost/spirit/home/karma/auxiliary/lazy.hpp
+++ b/boost/spirit/home/karma/auxiliary/lazy.hpp
@@ -59,7 +59,7 @@ namespace boost { namespace spirit { namespace karma
, typename Delimiter, typename Attribute>
bool lazy_generate_impl(Generator const& g, OutputIterator& sink
, Context& context, Delimiter const& delim
- , Attribute const& attr, mpl::true_)
+ , Attribute const& /* attr */, mpl::true_)
{
// If DeducedAuto is false (semantic actions is present), the
// component's attribute is unused.
diff --git a/boost/spirit/home/karma/nonterminal/rule.hpp b/boost/spirit/home/karma/nonterminal/rule.hpp
index 99d195fa5f..ab7db1265d 100644
--- a/boost/spirit/home/karma/nonterminal/rule.hpp
+++ b/boost/spirit/home/karma/nonterminal/rule.hpp
@@ -178,7 +178,7 @@ namespace boost { namespace spirit { namespace karma
}
template <typename Auto, typename Expr>
- static void define(rule& lhs, Expr const& expr, mpl::false_)
+ static void define(rule& /* lhs */, Expr const& /* expr */, mpl::false_)
{
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
diff --git a/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp b/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp
index 2ce7b743ad..a36893e57e 100644
--- a/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp
+++ b/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp
@@ -68,7 +68,7 @@ namespace boost { namespace spirit { namespace traits
typedef unsignedtype type; \
static type call(signedtype n) \
{ \
- return (n >= 0) ? n : (unsignedtype)(-n); \
+ return static_cast<unsignedtype>((n >= 0) ? n : -n); \
} \
} \
/**/
@@ -285,7 +285,7 @@ namespace boost { namespace spirit { namespace traits
{
static bool call(T n)
{
- if (!std::numeric_limits<T>::has_infinity)
+ if (!std::numeric_limits<T>::has_infinity)
return false;
return (n == std::numeric_limits<T>::infinity()) ? true : false;
}
@@ -771,4 +771,3 @@ namespace boost { namespace spirit { namespace karma
}}}
#endif
-
diff --git a/boost/spirit/home/lex/lexer/lexertl/functor.hpp b/boost/spirit/home/lex/lexer/lexertl/functor.hpp
index 79e5f073b4..d7b22413a8 100644
--- a/boost/spirit/home/lex/lexer/lexertl/functor.hpp
+++ b/boost/spirit/home/lex/lexer/lexertl/functor.hpp
@@ -98,11 +98,7 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
};
public:
- functor()
-#if defined(__PGI)
- : eof()
-#endif
- {}
+ functor() {}
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
// somehow VC7.1 needs this (meaningless) assignment operator
diff --git a/boost/spirit/home/lex/qi/plain_token.hpp b/boost/spirit/home/lex/qi/plain_token.hpp
index b77e2a9548..11961e3464 100644
--- a/boost/spirit/home/lex/qi/plain_token.hpp
+++ b/boost/spirit/home/lex/qi/plain_token.hpp
@@ -159,7 +159,7 @@ namespace boost { namespace spirit { namespace qi
typedef typename token_type::id_type id_type;
token_type const& t = *first;
- if (id_type(idmin) >= t.id() && id_type(idmin) <= t.id())
+ if (id_type(idmax) >= t.id() && id_type(idmin) <= t.id())
{
spirit::traits::assign_to(t, attr);
++first;
diff --git a/boost/spirit/home/qi/detail/alternative_function.hpp b/boost/spirit/home/qi/detail/alternative_function.hpp
index 0c400a90d4..88f6dad9a0 100644
--- a/boost/spirit/home/qi/detail/alternative_function.hpp
+++ b/boost/spirit/home/qi/detail/alternative_function.hpp
@@ -23,7 +23,7 @@ namespace boost { namespace spirit { namespace qi { namespace detail
template <typename Variant, typename Expected>
struct find_substitute
{
- // Get the typr from the variant that can be a substitute for Expected.
+ // Get the type from the variant that can be a substitute for Expected.
// If none is found, just return Expected
typedef Variant variant_type;
@@ -138,8 +138,9 @@ namespace boost { namespace spirit { namespace qi { namespace detail
template <typename Component>
bool call(Component const& component, mpl::false_) const
{
+ // fix for alternative.cpp test case, FHE 2016-07-28
return call_optional_or_variant(
- component, spirit::traits::not_is_variant<Attribute, qi::domain>());
+ component, mpl::not_<spirit::traits::not_is_optional<Attribute, qi::domain> >());
}
template <typename Component>
diff --git a/boost/spirit/home/qi/detail/construct.hpp b/boost/spirit/home/qi/detail/construct.hpp
index 5d8122f6a5..829190e98e 100644
--- a/boost/spirit/home/qi/detail/construct.hpp
+++ b/boost/spirit/home/qi/detail/construct.hpp
@@ -143,20 +143,20 @@ namespace boost { namespace spirit { namespace traits
#ifdef BOOST_HAS_LONG_LONG
template <typename Iterator>
- struct assign_to_attribute_from_iterators<long_long_type, Iterator>
+ struct assign_to_attribute_from_iterators<boost::long_long_type, Iterator>
{
static void
- call(Iterator const& first, Iterator const& last, long_long_type& attr)
+ call(Iterator const& first, Iterator const& last, boost::long_long_type& attr)
{
Iterator first_ = first;
qi::parse(first_, last, long_long_type(), attr);
}
};
template <typename Iterator>
- struct assign_to_attribute_from_iterators<ulong_long_type, Iterator>
+ struct assign_to_attribute_from_iterators<boost::ulong_long_type, Iterator>
{
static void
- call(Iterator const& first, Iterator const& last, ulong_long_type& attr)
+ call(Iterator const& first, Iterator const& last, boost::ulong_long_type& attr)
{
Iterator first_ = first;
qi::parse(first_, last, ulong_long_type(), attr);
diff --git a/boost/spirit/home/qi/detail/expectation_failure.hpp b/boost/spirit/home/qi/detail/expectation_failure.hpp
new file mode 100644
index 0000000000..3571e2f3f1
--- /dev/null
+++ b/boost/spirit/home/qi/detail/expectation_failure.hpp
@@ -0,0 +1,34 @@
+/*=============================================================================
+Copyright (c) 2001-2011 Joel de Guzman
+
+Distributed under the 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(SPIRIT_EXPECTATION_FAILURE_JULY_19_2016)
+#define SPIRIT_EXPECTATION_FAILURE_JULY_19_2016
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/support/info.hpp>
+
+#include <stdexcept>
+
+namespace boost { namespace spirit { namespace qi {
+ template <typename Iterator>
+ struct expectation_failure : std::runtime_error
+ {
+ expectation_failure(Iterator first_, Iterator last_, info const& what)
+ : std::runtime_error("boost::spirit::qi::expectation_failure")
+ , first(first_), last(last_), what_(what)
+ {}
+ ~expectation_failure() throw() {}
+
+ Iterator first;
+ Iterator last;
+ info what_;
+ };
+}}}
+
+#endif
diff --git a/boost/spirit/home/qi/directive.hpp b/boost/spirit/home/qi/directive.hpp
index 6d97ce491d..71e56f4efd 100644
--- a/boost/spirit/home/qi/directive.hpp
+++ b/boost/spirit/home/qi/directive.hpp
@@ -22,5 +22,6 @@
#include <boost/spirit/home/qi/directive/raw.hpp>
#include <boost/spirit/home/qi/directive/repeat.hpp>
#include <boost/spirit/home/qi/directive/skip.hpp>
+#include <boost/spirit/home/qi/directive/expect.hpp>
#endif
diff --git a/boost/spirit/home/qi/directive/expect.hpp b/boost/spirit/home/qi/directive/expect.hpp
new file mode 100644
index 0000000000..7892c9c32d
--- /dev/null
+++ b/boost/spirit/home/qi/directive/expect.hpp
@@ -0,0 +1,113 @@
+/*=============================================================================
+Copyright (c) 2016 Frank Hein, maxence business consulting gmbh
+
+Distributed under the 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 (SPIRIT_EXPECT_JULY_13_2016)
+#define SPIRIT_EXPECT_JULY_13_2016
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/spirit/home/qi/meta_compiler.hpp>
+#include <boost/spirit/home/support/has_semantic_action.hpp>
+#include <boost/spirit/home/qi/detail/attributes.hpp>
+#include <boost/spirit/home/qi/detail/expectation_failure.hpp>
+#include <boost/spirit/home/support/common_terminals.hpp>
+#include <boost/spirit/home/support/handles_container.hpp>
+#include <boost/spirit/home/support/unused.hpp>
+#include <boost/spirit/home/support/info.hpp>
+
+namespace boost { namespace spirit {
+ ///////////////////////////////////////////////////////////////////////////
+ // Enablers
+ ///////////////////////////////////////////////////////////////////////////
+ template <>
+ struct use_directive<qi::domain, tag::expect> // enables expect[p]
+ : mpl::true_ {};
+}}
+
+namespace boost { namespace spirit { namespace qi {
+
+#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+ using spirit::expect;
+#endif
+ using spirit::expect_type;
+
+ template <typename Subject>
+ struct expect_directive : unary_parser<expect_directive<Subject> >
+ {
+ typedef result_of::compile<domain, Subject> subject_type;
+
+ template <typename Context, typename Iterator>
+ struct attribute
+ {
+ typedef traits::attribute_of<subject_type, Context, Iterator>
+ type;
+ };
+
+ expect_directive(Subject const& subject_) : subject(subject_) {}
+
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper
+ , Attribute& attr_) const
+ {
+ typedef expectation_failure<Iterator> exception;
+
+ if (!subject.parse(first, last, context, skipper, attr_))
+ {
+ boost::throw_exception(
+ exception(first, last, subject.what(context)));
+#if defined(BOOST_NO_EXCEPTIONS)
+ return false; // for systems not supporting exceptions
+#endif
+ }
+ return true;
+ }
+
+ template <typename Context>
+ info what(Context& context) const
+ {
+ return info("expect", subject.what(context));
+ }
+
+ Subject subject;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Parser generators: make_xxx function (objects)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Subject, typename Modifiers>
+ struct make_directive<tag::expect, Subject, Modifiers>
+ {
+ typedef expect_directive<Subject> result_type;
+
+ result_type operator()
+ (unused_type, Subject const& subject, unused_type) const
+ {
+ return result_type(subject);
+ }
+ };
+
+}}}
+
+namespace boost { namespace spirit { namespace traits {
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Subject>
+ struct has_semantic_action<qi::expect_directive<Subject> >
+ : unary_has_semantic_action<Subject> {};
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Subject, typename Attribute
+ , typename Context, typename Iterator>
+ struct handles_container<
+ qi::expect_directive<Subject>, Attribute, Context, Iterator
+ >
+ : unary_handles_container<Subject, Attribute, Context, Iterator> {};
+}}}
+
+#endif
diff --git a/boost/spirit/home/qi/nonterminal/debug_handler.hpp b/boost/spirit/home/qi/nonterminal/debug_handler.hpp
index 6a9f536699..b7bab6fe6d 100644
--- a/boost/spirit/home/qi/nonterminal/debug_handler.hpp
+++ b/boost/spirit/home/qi/nonterminal/debug_handler.hpp
@@ -14,7 +14,7 @@
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/qi/nonterminal/rule.hpp>
#include <boost/spirit/home/qi/nonterminal/debug_handler_state.hpp>
-#include <boost/spirit/home/qi/operator/expect.hpp>
+#include <boost/spirit/home/qi/detail/expectation_failure.hpp>
#include <boost/function.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/vector.hpp>
diff --git a/boost/spirit/home/qi/numeric/detail/numeric_utils.hpp b/boost/spirit/home/qi/numeric/detail/numeric_utils.hpp
index ce9ad0f953..7f466ee65b 100644
--- a/boost/spirit/home/qi/numeric/detail/numeric_utils.hpp
+++ b/boost/spirit/home/qi/numeric/detail/numeric_utils.hpp
@@ -278,14 +278,20 @@ namespace boost { namespace spirit { namespace qi { namespace detail
#define SPIRIT_NUMERIC_INNER_LOOP(z, x, data) \
if (!check_max_digits<MaxDigits>::call(count + leading_zeros) \
|| it == last) \
+ { \
break; \
+ } \
ch = *it; \
if (!radix_check::is_valid(ch)) \
+ { \
break; \
+ } \
if (!extractor::call(ch, count, val)) \
{ \
if (IgnoreOverflowDigits) \
+ { \
first = it; \
+ } \
traits::assign_to(val, attr); \
return IgnoreOverflowDigits; \
} \
@@ -386,10 +392,14 @@ namespace boost { namespace spirit { namespace qi { namespace detail
///////////////////////////////////////////////////////////////////////////
#define SPIRIT_NUMERIC_INNER_LOOP(z, x, data) \
if (it == last) \
+ { \
break; \
+ } \
ch = *it; \
if (!radix_check::is_valid(ch)) \
+ { \
break; \
+ } \
if (!extractor::call(ch, count, val)) \
{ \
traits::assign_to(val, attr); \
diff --git a/boost/spirit/home/qi/numeric/detail/real_impl.hpp b/boost/spirit/home/qi/numeric/detail/real_impl.hpp
index 485df2727f..9aa5bb8bbd 100644
--- a/boost/spirit/home/qi/numeric/detail/real_impl.hpp
+++ b/boost/spirit/home/qi/numeric/detail/real_impl.hpp
@@ -32,7 +32,7 @@
namespace boost { namespace spirit { namespace traits
{
using spirit::traits::pow10;
-
+
namespace detail
{
template <typename T, typename AccT>
@@ -44,14 +44,14 @@ namespace boost { namespace spirit { namespace traits
n = T((acc_n / comp) * comp);
n += T(acc_n % comp);
}
-
+
template <typename T, typename AccT>
void compensate_roundoff(T& n, AccT acc_n, mpl::false_)
{
// no need to compensate
n = acc_n;
}
-
+
template <typename T, typename AccT>
void compensate_roundoff(T& n, AccT acc_n)
{
@@ -66,7 +66,7 @@ namespace boost { namespace spirit { namespace traits
if (exp >= 0)
{
int max_exp = std::numeric_limits<T>::max_exponent10;
-
+
// return false if exp exceeds the max_exp
// do this check only for primitive types!
if (is_floating_point<T>() && exp > max_exp)
@@ -80,7 +80,7 @@ namespace boost { namespace spirit { namespace traits
int min_exp = std::numeric_limits<T>::min_exponent10;
detail::compensate_roundoff(n, acc_n);
n /= pow10<T>(-min_exp);
-
+
// return false if (-exp + min_exp) exceeds the -min_exp
// do this check only for primitive types!
if (is_floating_point<T>() && (-exp + min_exp) > -min_exp)
@@ -284,7 +284,8 @@ namespace boost { namespace spirit { namespace qi { namespace detail
// If there is no number, disregard the exponent altogether.
// by resetting 'first' prior to the exponent prefix (e|E)
first = e_pos;
- n = static_cast<T>(acc_n);
+ // Scale the number by -frac_digits.
+ traits::scale(-frac_digits, n, acc_n);
}
}
else if (frac_digits)
diff --git a/boost/spirit/home/qi/operator/expect.hpp b/boost/spirit/home/qi/operator/expect.hpp
index ff279fd5d1..540372c33f 100644
--- a/boost/spirit/home/qi/operator/expect.hpp
+++ b/boost/spirit/home/qi/operator/expect.hpp
@@ -14,11 +14,11 @@
#include <boost/spirit/home/qi/operator/sequence_base.hpp>
#include <boost/spirit/home/qi/detail/expect_function.hpp>
+#include <boost/spirit/home/qi/detail/expectation_failure.hpp>
#include <boost/spirit/home/qi/meta_compiler.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/support/info.hpp>
-#include <stdexcept>
namespace boost { namespace spirit
{
@@ -36,27 +36,13 @@ namespace boost { namespace spirit
namespace boost { namespace spirit { namespace qi
{
- template <typename Iterator>
- struct expectation_failure : std::runtime_error
- {
- expectation_failure(Iterator first_, Iterator last_, info const& what)
- : std::runtime_error("boost::spirit::qi::expectation_failure")
- , first(first_), last(last_), what_(what)
- {}
- ~expectation_failure() throw() {}
-
- Iterator first;
- Iterator last;
- info what_;
- };
-
template <typename Elements>
- struct expect : sequence_base<expect<Elements>, Elements>
+ struct expect_operator : sequence_base<expect_operator<Elements>, Elements>
{
- friend struct sequence_base<expect<Elements>, Elements>;
+ friend struct sequence_base<expect_operator<Elements>, Elements>;
- expect(Elements const& elements)
- : sequence_base<expect<Elements>, Elements>(elements) {}
+ expect_operator(Elements const& elements)
+ : sequence_base<expect_operator<Elements>, Elements>(elements) {}
private:
@@ -73,7 +59,7 @@ namespace boost { namespace spirit { namespace qi
(first, last, context, skipper);
}
- std::string id() const { return "expect"; }
+ std::string id() const { return "expect_operator"; }
};
///////////////////////////////////////////////////////////////////////////
@@ -81,7 +67,7 @@ namespace boost { namespace spirit { namespace qi
///////////////////////////////////////////////////////////////////////////
template <typename Elements, typename Modifiers>
struct make_composite<proto::tag::greater, Elements, Modifiers>
- : make_nary_composite<Elements, expect>
+ : make_nary_composite<Elements, expect_operator>
{};
}}}
@@ -89,13 +75,13 @@ namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Elements>
- struct has_semantic_action<qi::expect<Elements> >
+ struct has_semantic_action<qi::expect_operator<Elements> >
: nary_has_semantic_action<Elements> {};
///////////////////////////////////////////////////////////////////////////
template <typename Elements, typename Attribute, typename Context
, typename Iterator>
- struct handles_container<qi::expect<Elements>, Attribute, Context
+ struct handles_container<qi::expect_operator<Elements>, Attribute, Context
, Iterator>
: mpl::true_ {};
}}}
diff --git a/boost/spirit/home/support/attributes.hpp b/boost/spirit/home/support/attributes.hpp
index 889e3a370b..dd89521404 100644
--- a/boost/spirit/home/support/attributes.hpp
+++ b/boost/spirit/home/support/attributes.hpp
@@ -1032,8 +1032,7 @@ namespace boost { namespace spirit { namespace traits
template <typename T>
void swap_impl(T& a, T& b)
{
- using namespace std;
- swap(a, b);
+ boost::swap(a, b);
}
template <typename A>
diff --git a/boost/spirit/home/support/common_terminals.hpp b/boost/spirit/home/support/common_terminals.hpp
index 2c7772df66..cab01c1c27 100644
--- a/boost/spirit/home/support/common_terminals.hpp
+++ b/boost/spirit/home/support/common_terminals.hpp
@@ -83,6 +83,7 @@ namespace boost { namespace spirit
( strict, strict_type )
( relaxed, relaxed_type )
( duplicate, duplicate_type )
+ ( expect, expect_type )
)
// Our extended terminals
diff --git a/boost/spirit/home/support/detail/lexer/generator.hpp b/boost/spirit/home/support/detail/lexer/generator.hpp
index daa06e7944..103c834978 100644
--- a/boost/spirit/home/support/detail/lexer/generator.hpp
+++ b/boost/spirit/home/support/detail/lexer/generator.hpp
@@ -16,6 +16,7 @@
#include "parser/tree/node.hpp"
#include "parser/parser.hpp"
#include "containers/ptr_list.hpp"
+#include <boost/move/unique_ptr.hpp>
#include "rules.hpp"
#include "state_machine.hpp"
@@ -116,10 +117,10 @@ public:
protected:
typedef detail::basic_charset<CharT> charset;
typedef detail::ptr_list<charset> charset_list;
- typedef std::auto_ptr<charset> charset_ptr;
+ typedef boost::movelib::unique_ptr<charset> charset_ptr;
typedef detail::equivset equivset;
typedef detail::ptr_list<equivset> equivset_list;
- typedef std::auto_ptr<equivset> equivset_ptr;
+ typedef boost::movelib::unique_ptr<equivset> equivset_ptr;
typedef typename charset::index_set index_set;
typedef std::vector<index_set> index_set_vector;
typedef detail::basic_parser<CharT> parser;
@@ -377,8 +378,8 @@ protected:
if (followpos_->empty ()) return npos;
std::size_t index_ = 0;
- std::auto_ptr<node_set> set_ptr_ (new node_set);
- std::auto_ptr<node_vector> vector_ptr_ (new node_vector);
+ boost::movelib::unique_ptr<node_set> set_ptr_ (new node_set);
+ boost::movelib::unique_ptr<node_vector> vector_ptr_ (new node_vector);
for (typename detail::node::node_vector::const_iterator iter_ =
followpos_->begin (), end_ = followpos_->end ();
@@ -494,21 +495,13 @@ protected:
delete *l_iter_;
*l_iter_ = overlap_.release ();
- // VC++ 6 Hack:
- charset_ptr temp_overlap_ (new charset);
-
- overlap_ = temp_overlap_;
+ overlap_.reset (new charset);
++iter_;
}
else if (r_->empty ())
{
- delete r_.release ();
- r_ = overlap_;
-
- // VC++ 6 Hack:
- charset_ptr temp_overlap_ (new charset);
-
- overlap_ = temp_overlap_;
+ overlap_.swap (r_);
+ overlap_.reset (new charset);
break;
}
else
@@ -517,10 +510,7 @@ protected:
static_cast<charset *>(0));
*iter_ = overlap_.release ();
- // VC++ 6 Hack:
- charset_ptr temp_overlap_ (new charset);
-
- overlap_ = temp_overlap_;
+ overlap_.reset(new charset);
++iter_;
end_ = lhs_->end ();
}
@@ -642,21 +632,13 @@ protected:
delete *l_iter_;
*l_iter_ = overlap_.release ();
- // VC++ 6 Hack:
- equivset_ptr temp_overlap_ (new equivset);
-
- overlap_ = temp_overlap_;
+ overlap_.reset (new equivset);
++iter_;
}
else if (r_->empty ())
{
- delete r_.release ();
- r_ = overlap_;
-
- // VC++ 6 Hack:
- equivset_ptr temp_overlap_ (new equivset);
-
- overlap_ = temp_overlap_;
+ overlap_.swap (r_);
+ overlap_.reset (new equivset);
break;
}
else
@@ -665,10 +647,7 @@ protected:
static_cast<equivset *>(0));
*iter_ = overlap_.release ();
- // VC++ 6 Hack:
- equivset_ptr temp_overlap_ (new equivset);
-
- overlap_ = temp_overlap_;
+ overlap_.reset (new equivset);
++iter_;
end_ = lhs_->end ();
}
diff --git a/boost/spirit/home/support/detail/pow10.hpp b/boost/spirit/home/support/detail/pow10.hpp
index b49bb581fd..e21a4dc571 100644
--- a/boost/spirit/home/support/detail/pow10.hpp
+++ b/boost/spirit/home/support/detail/pow10.hpp
@@ -13,6 +13,7 @@
#pragma once
#endif
+#include <cfloat>
#include <boost/config/no_tr1/cmath.hpp>
#include <boost/limits.hpp>
#include <boost/spirit/home/support/unused.hpp>
diff --git a/boost/spirit/home/support/iterators/multi_pass.hpp b/boost/spirit/home/support/iterators/multi_pass.hpp
index 3fc244034f..1c31d7e256 100644
--- a/boost/spirit/home/support/iterators/multi_pass.hpp
+++ b/boost/spirit/home/support/iterators/multi_pass.hpp
@@ -148,19 +148,19 @@ namespace boost { namespace spirit
return policies_base_type::less_than(*this, y);
}
- bool operator!=(multi_pass const& y)
+ bool operator!=(multi_pass const& y) const
{
return !(*this == y);
}
- bool operator>(multi_pass const& y)
+ bool operator>(multi_pass const& y) const
{
return y < *this;
}
- bool operator>=(multi_pass const& y)
+ bool operator>=(multi_pass const& y) const
{
return !(*this < y);
}
- bool operator<=(multi_pass const& y)
+ bool operator<=(multi_pass const& y) const
{
return !(y < *this);
}
diff --git a/boost/spirit/home/x3/auxiliary/attr.hpp b/boost/spirit/home/x3/auxiliary/attr.hpp
index 5b3c7a5d85..6471bd90df 100644
--- a/boost/spirit/home/x3/auxiliary/attr.hpp
+++ b/boost/spirit/home/x3/auxiliary/attr.hpp
@@ -40,8 +40,8 @@ namespace boost { namespace spirit { namespace x3
template <typename Iterator, typename Context
, typename RuleContext, typename Attribute>
- bool parse(Iterator& first, Iterator const& last
- , Context const& context, RuleContext&, Attribute& attr_) const
+ bool parse(Iterator& /* first */, Iterator const& /* last */
+ , Context const& /* context */, RuleContext&, Attribute& attr_) const
{
// $$$ Change to copy_to once we have it $$$
traits::move_to(value_, attr_);
@@ -76,8 +76,8 @@ namespace boost { namespace spirit { namespace x3
template <typename Iterator, typename Context
, typename RuleContext, typename Attribute>
- bool parse(Iterator& first, Iterator const& last
- , Context const& context, RuleContext&, Attribute& attr_) const
+ bool parse(Iterator& /* first */, Iterator const& /* last */
+ , Context const& /* context */, RuleContext&, Attribute& attr_) const
{
// $$$ Change to copy_to once we have it $$$
traits::move_to(value_ + 0, value_ + N, attr_);
diff --git a/boost/spirit/home/x3/auxiliary/eps.hpp b/boost/spirit/home/x3/auxiliary/eps.hpp
index 816eea7b0f..3d4ae9a57d 100644
--- a/boost/spirit/home/x3/auxiliary/eps.hpp
+++ b/boost/spirit/home/x3/auxiliary/eps.hpp
@@ -45,7 +45,7 @@ namespace boost { namespace spirit { namespace x3
template <typename Iterator, typename Context, typename Attribute>
bool parse(Iterator& first, Iterator const& last
- , Context const& context, unused_type, Attribute& attr) const
+ , Context const& context, unused_type, Attribute& /* attr */) const
{
x3::skip_over(first, last, context);
return f(x3::get<rule_context_tag>(context));
diff --git a/boost/spirit/home/x3/char/char.hpp b/boost/spirit/home/x3/char/char.hpp
index 5cfd720152..8cd213a2bc 100644
--- a/boost/spirit/home/x3/char/char.hpp
+++ b/boost/spirit/home/x3/char/char.hpp
@@ -38,6 +38,7 @@ namespace boost { namespace spirit { namespace x3
using standard::char_;
using standard::lit;
+#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
namespace standard_wide
{
typedef any_char<char_encoding::standard_wide> char_type;
@@ -49,6 +50,7 @@ namespace boost { namespace spirit { namespace x3
return { ch };
}
}
+#endif
namespace ascii
{
@@ -103,6 +105,7 @@ namespace boost { namespace spirit { namespace x3
}
};
+#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
template <>
struct as_parser<wchar_t>
{
@@ -117,6 +120,7 @@ namespace boost { namespace spirit { namespace x3
return { ch };
}
};
+#endif
template <>
struct as_parser<char [2]>
@@ -133,6 +137,7 @@ namespace boost { namespace spirit { namespace x3
}
};
+#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
template <>
struct as_parser<wchar_t [2]>
{
@@ -147,6 +152,7 @@ namespace boost { namespace spirit { namespace x3
return { ch[0] };
}
};
+#endif
}
diff --git a/boost/spirit/home/x3/char/char_class.hpp b/boost/spirit/home/x3/char/char_class.hpp
index 7fae90fdcd..0af6f01d9f 100644
--- a/boost/spirit/home/x3/char/char_class.hpp
+++ b/boost/spirit/home/x3/char/char_class.hpp
@@ -93,7 +93,9 @@ namespace boost { namespace spirit { namespace x3
/***/
BOOST_SPIRIT_X3_CHAR_CLASSES(standard)
+#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
BOOST_SPIRIT_X3_CHAR_CLASSES(standard_wide)
+#endif
BOOST_SPIRIT_X3_CHAR_CLASSES(ascii)
BOOST_SPIRIT_X3_CHAR_CLASSES(iso8859_1)
diff --git a/boost/spirit/home/x3/char/char_set.hpp b/boost/spirit/home/x3/char/char_set.hpp
index 3a8f986456..1bff83ec6b 100644
--- a/boost/spirit/home/x3/char/char_set.hpp
+++ b/boost/spirit/home/x3/char/char_set.hpp
@@ -115,7 +115,7 @@ namespace boost { namespace spirit { namespace x3
struct get_info<char_set<Encoding, Attribute>>
{
typedef std::string result_type;
- std::string operator()(char_set<Encoding, Attribute> const& p) const
+ std::string operator()(char_set<Encoding, Attribute> const& /* p */) const
{
return "char-set";
}
diff --git a/boost/spirit/home/x3/core/call.hpp b/boost/spirit/home/x3/core/call.hpp
index 9674c93efe..8a5deedb73 100644
--- a/boost/spirit/home/x3/core/call.hpp
+++ b/boost/spirit/home/x3/core/call.hpp
@@ -52,7 +52,7 @@ namespace boost { namespace spirit { namespace x3
}
template <typename F, typename Context>
- auto call(F f, Context const& context, mpl::false_)
+ auto call(F f, Context const& /* context */, mpl::false_)
{
return f();
}
diff --git a/boost/spirit/home/x3/core/detail/parse_into_container.hpp b/boost/spirit/home/x3/core/detail/parse_into_container.hpp
index 96424a4278..45ecc41ae0 100644
--- a/boost/spirit/home/x3/core/detail/parse_into_container.hpp
+++ b/boost/spirit/home/x3/core/detail/parse_into_container.hpp
@@ -202,7 +202,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
static bool call(
Parser const& parser
, Iterator& first, Iterator const& last, Context const& context
- , RContext& rcontext, Attribute& attr, mpl::false_)
+ , RContext& rcontext, Attribute& /* attr */, mpl::false_)
{
return parser.parse(first, last, context, rcontext, unused);
}
@@ -251,7 +251,13 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
, Iterator& first, Iterator const& last
, Context const& context, RContext& rcontext, Attribute& attr, mpl::true_)
{
- return parser.parse(first, last, context, rcontext, attr);
+ if (attr.empty())
+ return parser.parse(first, last, context, rcontext, attr);
+ Attribute rest;
+ bool r = parser.parse(first, last, context, rcontext, rest);
+ if (r)
+ attr.insert(attr.end(), rest.begin(), rest.end());
+ return r;
}
template <typename Iterator, typename Attribute>
diff --git a/boost/spirit/home/x3/core/parser.hpp b/boost/spirit/home/x3/core/parser.hpp
index 0df69304e0..27115b8de4 100644
--- a/boost/spirit/home/x3/core/parser.hpp
+++ b/boost/spirit/home/x3/core/parser.hpp
@@ -18,6 +18,8 @@
#include <boost/spirit/home/x3/support/context.hpp>
#include <boost/spirit/home/x3/support/traits/has_attribute.hpp>
#include <boost/spirit/home/x3/support/utility/sfinae.hpp>
+#include <boost/core/ignore_unused.hpp>
+#include <boost/assert.hpp>
#include <string>
#if !defined(BOOST_SPIRIT_X3_NO_RTTI)
@@ -63,6 +65,23 @@ namespace boost { namespace spirit { namespace x3
}
};
+ namespace detail {
+ template <typename Parser>
+ static void assert_initialized_rule(Parser const& p) {
+ boost::ignore_unused(p);
+
+ // Assert that we are not copying an unitialized static rule. If
+ // the static is in another TU, it may be initialized after we copy
+ // it. If so, its name member will be nullptr.
+ //
+ // Rather than hardcoding behaviour for rule-type subject parsers,
+ // we simply allow get_info<> to do the check in debug builds.
+#ifndef NDEBUG
+ what(p); // note: allows get_info<> to diagnose the issue
+#endif
+ }
+ }
+
struct unary_category;
struct binary_category;
@@ -74,7 +93,7 @@ namespace boost { namespace spirit { namespace x3
static bool const has_action = Subject::has_action;
unary_parser(Subject const& subject)
- : subject(subject) {}
+ : subject(subject) { detail::assert_initialized_rule(subject); }
unary_parser const& get_unary() const { return *this; }
@@ -91,7 +110,11 @@ namespace boost { namespace spirit { namespace x3
left_type::has_action || right_type::has_action;
binary_parser(Left const& left, Right const& right)
- : left(left), right(right) {}
+ : left(left), right(right)
+ {
+ detail::assert_initialized_rule(left);
+ detail::assert_initialized_rule(right);
+ }
binary_parser const& get_binary() const { return *this; }
diff --git a/boost/spirit/home/x3/nonterminal/detail/rule.hpp b/boost/spirit/home/x3/nonterminal/detail/rule.hpp
index e07b067718..dda44e1f50 100644
--- a/boost/spirit/home/x3/nonterminal/detail/rule.hpp
+++ b/boost/spirit/home/x3/nonterminal/detail/rule.hpp
@@ -7,6 +7,7 @@
#if !defined(BOOST_SPIRIT_X3_DETAIL_RULE_JAN_08_2012_0326PM)
#define BOOST_SPIRIT_X3_DETAIL_RULE_JAN_08_2012_0326PM
+#include <boost/core/ignore_unused.hpp>
#include <boost/spirit/home/x3/auxiliary/guard.hpp>
#include <boost/spirit/home/x3/core/parser.hpp>
#include <boost/spirit/home/x3/core/skip_over.hpp>
@@ -138,7 +139,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
template <typename ID, typename RHS, typename Context>
Context const&
- make_rule_context(RHS const& rhs, Context const& context
+ make_rule_context(RHS const& /* rhs */, Context const& context
, mpl::false_ /* is_default_parse_rule */)
{
return context;
@@ -156,8 +157,8 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
{
template <typename Iterator, typename Context, typename ActualAttribute>
static bool call_on_success(
- Iterator& first, Iterator const& last
- , Context const& context, ActualAttribute& attr
+ Iterator& /* first */, Iterator const& /* last */
+ , Context const& /* context */, ActualAttribute& /* attr */
, mpl::false_ /* No on_success handler */ )
{
return true;
@@ -285,7 +286,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
static bool parse_rhs(
RHS const& rhs
, Iterator& first, Iterator const& last
- , Context const& context, RContext& rcontext, ActualAttribute& attr
+ , Context const& context, RContext& rcontext, ActualAttribute& /* attr */
, mpl::true_)
{
return parse_rhs_main(rhs, first, last, context, rcontext, unused);
@@ -300,6 +301,8 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
, Context const& context, ActualAttribute& attr
, ExplicitAttrPropagation)
{
+ boost::ignore_unused(rule_name);
+
typedef traits::make_attribute<Attribute, ActualAttribute> make_attribute;
// do down-stream transformation, provides attribute for
@@ -325,9 +328,8 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
// traits::post_transform when, for example,
// ActualAttribute is a recursive variant).
#if defined(BOOST_SPIRIT_X3_DEBUG)
- typedef typename make_attribute::type dbg_attribute_type;
- context_debug<Iterator, dbg_attribute_type>
- dbg(rule_name, first, last, dbg_attribute_type(attr_), ok_parse);
+ context_debug<Iterator, transform_attr>
+ dbg(rule_name, first, last, attr_, ok_parse);
#endif
ok_parse = parse_rhs(rhs, first, last, context, attr_, attr_
, mpl::bool_
diff --git a/boost/spirit/home/x3/nonterminal/rule.hpp b/boost/spirit/home/x3/nonterminal/rule.hpp
index 56075f34d7..ffed1fe965 100644
--- a/boost/spirit/home/x3/nonterminal/rule.hpp
+++ b/boost/spirit/home/x3/nonterminal/rule.hpp
@@ -20,15 +20,12 @@
namespace boost { namespace spirit { namespace x3
{
- template <typename ID>
- struct identity {};
-
// default parse_rule implementation
template <typename ID, typename Attribute, typename Iterator
, typename Context, typename ActualAttribute>
inline detail::default_parse_rule_result
parse_rule(
- rule<ID, Attribute> rule_
+ rule<ID, Attribute> /* rule_ */
, Iterator& first, Iterator const& last
, Context const& context, ActualAttribute& attr)
{
@@ -137,7 +134,8 @@ namespace boost { namespace spirit { namespace x3
typedef std::string result_type;
std::string operator()(T const& r) const
{
- return r.name;
+ BOOST_ASSERT_MSG(r.name, "uninitialized rule"); // static initialization order fiasco
+ return r.name? r.name : "uninitialized";
}
};
@@ -156,7 +154,7 @@ namespace boost { namespace spirit { namespace x3
#define BOOST_SPIRIT_DEFINE_(r, data, rule_name) \
template <typename Iterator, typename Context, typename Attribute> \
inline bool parse_rule( \
- decltype(rule_name) rule_ \
+ decltype(rule_name) /* rule_ */ \
, Iterator& first, Iterator const& last \
, Context const& context, Attribute& attr) \
{ \
diff --git a/boost/spirit/home/x3/numeric.hpp b/boost/spirit/home/x3/numeric.hpp
index ae4d9caa26..3acff052d1 100644
--- a/boost/spirit/home/x3/numeric.hpp
+++ b/boost/spirit/home/x3/numeric.hpp
@@ -10,6 +10,8 @@
#include <boost/spirit/home/x3/numeric/bool.hpp>
#include <boost/spirit/home/x3/numeric/int.hpp>
#include <boost/spirit/home/x3/numeric/uint.hpp>
+#ifndef BOOST_SPIRIT_NO_REAL_NUMBERS
#include <boost/spirit/home/x3/numeric/real.hpp>
+#endif
#endif
diff --git a/boost/spirit/home/x3/numeric/bool.hpp b/boost/spirit/home/x3/numeric/bool.hpp
index 1fd7018b0f..d5c53c0474 100644
--- a/boost/spirit/home/x3/numeric/bool.hpp
+++ b/boost/spirit/home/x3/numeric/bool.hpp
@@ -114,6 +114,7 @@ namespace boost { namespace spirit { namespace x3
false_type const false_ = { false };
}
+#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
namespace standard_wide
{
typedef bool_parser<bool, char_encoding::standard_wide> bool_type;
@@ -125,6 +126,7 @@ namespace boost { namespace spirit { namespace x3
typedef literal_bool_parser<bool, char_encoding::standard_wide> false_type;
false_type const false_ = { false };
}
+#endif
namespace ascii
{
diff --git a/boost/spirit/home/x3/operator/detail/alternative.hpp b/boost/spirit/home/x3/operator/detail/alternative.hpp
index 9fbc4f4dc4..0043710320 100644
--- a/boost/spirit/home/x3/operator/detail/alternative.hpp
+++ b/boost/spirit/home/x3/operator/detail/alternative.hpp
@@ -226,7 +226,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
struct move_if_not_alternative
{
template<typename T1, typename T2>
- static void call(T1& attr_, T2& attr) {}
+ static void call(T1& /* attr_ */, T2& /* attr */) {}
};
template <>
diff --git a/boost/spirit/home/x3/string/literal_string.hpp b/boost/spirit/home/x3/string/literal_string.hpp
index 5066fe18a9..486dc807b3 100644
--- a/boost/spirit/home/x3/string/literal_string.hpp
+++ b/boost/spirit/home/x3/string/literal_string.hpp
@@ -77,6 +77,7 @@ namespace boost { namespace spirit { namespace x3
}
}
+#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
namespace standard_wide
{
inline literal_string<wchar_t const*, char_encoding::standard_wide>
@@ -103,6 +104,7 @@ namespace boost { namespace spirit { namespace x3
return { s };
}
}
+#endif
namespace ascii
{
@@ -162,8 +164,10 @@ namespace boost { namespace spirit { namespace x3
using standard::string;
using standard::lit;
+#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
using standard_wide::string;
using standard_wide::lit;
+#endif
namespace extension
{
@@ -185,6 +189,7 @@ namespace boost { namespace spirit { namespace x3
template <int N>
struct as_parser<char const[N]> : as_parser<char[N]> {};
+#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
template <int N>
struct as_parser<wchar_t[N]>
{
@@ -202,6 +207,7 @@ namespace boost { namespace spirit { namespace x3
template <int N>
struct as_parser<wchar_t const[N]> : as_parser<wchar_t[N]> {};
+#endif
template <>
struct as_parser<char const*>
diff --git a/boost/spirit/home/x3/string/symbols.hpp b/boost/spirit/home/x3/string/symbols.hpp
index 1846c57bad..f9ba4cd392 100644
--- a/boost/spirit/home/x3/string/symbols.hpp
+++ b/boost/spirit/home/x3/string/symbols.hpp
@@ -343,11 +343,13 @@ namespace boost { namespace spirit { namespace x3
using standard::symbols;
+#ifndef BOOST_SPIRIT_NO_STANDARD_WIDE
namespace standard_wide
{
template <typename T = unused_type>
using symbols = symbols_parser<char_encoding::standard_wide, T>;
}
+#endif
namespace ascii
{
diff --git a/boost/spirit/home/x3/support/context.hpp b/boost/spirit/home/x3/support/context.hpp
index 592ce3ff76..9b24a3397c 100644
--- a/boost/spirit/home/x3/support/context.hpp
+++ b/boost/spirit/home/x3/support/context.hpp
@@ -74,12 +74,12 @@ namespace boost { namespace spirit { namespace x3
{
return { val };
}
-
+
namespace detail
{
template <typename ID, typename T, typename Next, typename FoundVal>
inline Next const&
- make_unique_context(T& val, Next const& next, FoundVal&)
+ make_unique_context(T& /* val */, Next const& next, FoundVal&)
{
return next;
}
@@ -91,7 +91,7 @@ namespace boost { namespace spirit { namespace x3
return { val, next };
}
}
-
+
template <typename ID, typename T, typename Next>
inline auto
make_unique_context(T& val, Next const& next)
diff --git a/boost/spirit/home/x3/support/traits/container_traits.hpp b/boost/spirit/home/x3/support/traits/container_traits.hpp
index b05764969c..7dcf798958 100644
--- a/boost/spirit/home/x3/support/traits/container_traits.hpp
+++ b/boost/spirit/home/x3/support/traits/container_traits.hpp
@@ -159,7 +159,7 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
{
private:
template <typename Iterator>
- static void reserve(Container& c, Iterator first, Iterator last, mpl::false_)
+ static void reserve(Container& /* c */, Iterator /* first */, Iterator /* last */, mpl::false_)
{
// Not all containers have "reserve"
}
@@ -199,7 +199,7 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
}
template <typename Iterator>
- inline bool append(unused_type, Iterator first, Iterator last)
+ inline bool append(unused_type, Iterator /* first */, Iterator /* last */)
{
return true;
}
diff --git a/boost/spirit/include/qi_expect.hpp b/boost/spirit/include/qi_expect.hpp
index bfcd7396f7..4dcbe632b1 100644
--- a/boost/spirit/include/qi_expect.hpp
+++ b/boost/spirit/include/qi_expect.hpp
@@ -14,5 +14,6 @@
#endif
#include <boost/spirit/home/qi/operator/expect.hpp>
+#include <boost/spirit/home/qi/directive/expect.hpp>
#endif
diff --git a/boost/spirit/include/version.hpp b/boost/spirit/include/version.hpp
index 90f8b53313..a6afc61755 100644
--- a/boost/spirit/include/version.hpp
+++ b/boost/spirit/include/version.hpp
@@ -14,7 +14,7 @@
// This is the version of the current Spirit distribution
//
///////////////////////////////////////////////////////////////////////////////
-#define SPIRIT_VERSION 0x2053
+#define SPIRIT_VERSION 0x2054
#define SPIRIT_PIZZA_VERSION SUPER_HOT_SPANISH_SARDINES // :-O
#endif
diff --git a/boost/stacktrace.hpp b/boost/stacktrace.hpp
new file mode 100644
index 0000000000..6e1ec0489a
--- /dev/null
+++ b/boost/stacktrace.hpp
@@ -0,0 +1,19 @@
+// Copyright Antony Polukhin, 2016-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_STACKTRACE_HPP
+#define BOOST_STACKTRACE_HPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/stacktrace/frame.hpp>
+#include <boost/stacktrace/stacktrace.hpp>
+#include <boost/stacktrace/safe_dump_to.hpp>
+
+#endif // BOOST_STACKTRACE_HPP
diff --git a/boost/stacktrace/detail/addr2line_impls.hpp b/boost/stacktrace/detail/addr2line_impls.hpp
new file mode 100644
index 0000000000..e314fe9f31
--- /dev/null
+++ b/boost/stacktrace/detail/addr2line_impls.hpp
@@ -0,0 +1,225 @@
+// Copyright Antony Polukhin, 2016-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_STACKTRACE_DETAIL_ADDR2LINE_IMPLS_HPP
+#define BOOST_STACKTRACE_DETAIL_ADDR2LINE_IMPLS_HPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/stacktrace/detail/to_hex_array.hpp>
+#include <boost/core/demangle.hpp>
+#include <boost/lexical_cast.hpp>
+#include <cstdio>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+
+namespace boost { namespace stacktrace { namespace detail {
+
+
+#if defined(BOOST_STACKTRACE_ADDR2LINE_LOCATION) && !defined(BOOST_NO_CXX11_CONSTEXPR)
+
+constexpr bool is_abs_path(const char* path) BOOST_NOEXCEPT {
+ return *path != '\0' && (
+ *path == ':' || *path == '/' || is_abs_path(path + 1)
+ );
+}
+
+#endif
+
+class addr2line_pipe {
+ ::FILE* p;
+ ::pid_t pid;
+
+public:
+ explicit addr2line_pipe(const char *flag, const char* exec_path, const char* addr) BOOST_NOEXCEPT
+ : p(0)
+ , pid(0)
+ {
+ int pdes[2];
+ #ifdef BOOST_STACKTRACE_ADDR2LINE_LOCATION
+ char prog_name[] = BOOST_STRINGIZE( BOOST_STACKTRACE_ADDR2LINE_LOCATION );
+ #if !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_STATIC_ASSERT)
+ static_assert(
+ boost::stacktrace::detail::is_abs_path( BOOST_STRINGIZE( BOOST_STACKTRACE_ADDR2LINE_LOCATION ) ),
+ "BOOST_STACKTRACE_ADDR2LINE_LOCATION must be an absolute path"
+ );
+ #endif
+
+ #else
+ char prog_name[] = "/usr/bin/addr2line";
+ #endif
+
+ char* argp[] = {
+ prog_name,
+ const_cast<char*>(flag),
+ const_cast<char*>(exec_path),
+ const_cast<char*>(addr),
+ 0
+ };
+
+ if (::pipe(pdes) < 0) {
+ return;
+ }
+
+ pid = ::fork();
+ switch (pid) {
+ case -1:
+ // Failed...
+ ::close(pdes[0]);
+ ::close(pdes[1]);
+ return;
+
+ case 0:
+ // We are the child.
+ ::close(STDERR_FILENO);
+ ::close(pdes[0]);
+ if (pdes[1] != STDOUT_FILENO) {
+ ::dup2(pdes[1], STDOUT_FILENO);
+ }
+
+ // Do not use `execlp()`, `execvp()`, and `execvpe()` here!
+ // `exec*p*` functions are vulnerable to PATH variable evaluation attacks.
+ ::execv(prog_name, argp);
+ ::_exit(127);
+ }
+
+ p = ::fdopen(pdes[0], "r");
+ ::close(pdes[1]);
+ }
+
+ operator ::FILE*() const BOOST_NOEXCEPT {
+ return p;
+ }
+
+ ~addr2line_pipe() BOOST_NOEXCEPT {
+ if (p) {
+ ::fclose(p);
+ int pstat = 0;
+ ::kill(pid, SIGKILL);
+ ::waitpid(pid, &pstat, 0);
+ }
+ }
+};
+
+inline std::string addr2line(const char* flag, const void* addr) {
+ std::string res;
+
+ boost::stacktrace::detail::location_from_symbol loc(addr);
+ if (!loc.empty()) {
+ res = loc.name();
+ } else {
+ res.resize(16);
+ int rlin_size = ::readlink("/proc/self/exe", &res[0], res.size() - 1);
+ while (rlin_size == static_cast<int>(res.size() - 1)) {
+ res.resize(res.size() * 4);
+ rlin_size = ::readlink("/proc/self/exe", &res[0], res.size() - 1);
+ }
+ if (rlin_size == -1) {
+ res.clear();
+ return res;
+ }
+ res.resize(rlin_size);
+ }
+
+ addr2line_pipe p(flag, res.c_str(), to_hex_array(addr).data());
+ res.clear();
+
+ if (!p) {
+ return res;
+ }
+
+ char data[32];
+ while (!::feof(p)) {
+ if (::fgets(data, sizeof(data), p)) {
+ res += data;
+ } else {
+ break;
+ }
+ }
+
+ // Trimming
+ while (!res.empty() && (res[res.size() - 1] == '\n' || res[res.size() - 1] == '\r')) {
+ res.erase(res.size() - 1);
+ }
+
+ return res;
+}
+
+
+struct to_string_using_addr2line {
+ std::string res;
+ void prepare_function_name(const void* addr) {
+ res = boost::stacktrace::frame(addr).name();
+ }
+
+ bool prepare_source_location(const void* addr) {
+ //return addr2line("-Cfipe", addr); // Does not seem to work in all cases
+ std::string source_line = boost::stacktrace::detail::addr2line("-Cpe", addr);
+ if (!source_line.empty() && source_line[0] != '?') {
+ res += " at ";
+ res += source_line;
+ return true;
+ }
+
+ return false;
+ }
+};
+
+template <class Base> class to_string_impl_base;
+typedef to_string_impl_base<to_string_using_addr2line> to_string_impl;
+
+inline std::string name_impl(const void* addr) {
+ std::string res = boost::stacktrace::detail::addr2line("-fe", addr);
+ res = res.substr(0, res.find_last_of('\n'));
+ res = boost::core::demangle(res.c_str());
+
+ if (res == "??") {
+ res.clear();
+ }
+
+ return res;
+}
+
+} // namespace detail
+
+std::string frame::source_file() const {
+ std::string res;
+ res = boost::stacktrace::detail::addr2line("-e", addr_);
+ res = res.substr(0, res.find_last_of(':'));
+ if (res == "??") {
+ res.clear();
+ }
+
+ return res;
+}
+
+
+std::size_t frame::source_line() const {
+ std::size_t line_num = 0;
+ std::string res = boost::stacktrace::detail::addr2line("-e", addr_);
+ const std::size_t last = res.find_last_of(':');
+ if (last == std::string::npos) {
+ return 0;
+ }
+ res = res.substr(last + 1);
+
+ if (!boost::conversion::try_lexical_convert(res, line_num)) {
+ return 0;
+ }
+
+ return line_num;
+}
+
+
+}} // namespace boost::stacktrace
+
+#endif // BOOST_STACKTRACE_DETAIL_ADDR2LINE_IMPLS_HPP
diff --git a/boost/stacktrace/detail/collect_msvc.ipp b/boost/stacktrace/detail/collect_msvc.ipp
new file mode 100644
index 0000000000..d75df558f3
--- /dev/null
+++ b/boost/stacktrace/detail/collect_msvc.ipp
@@ -0,0 +1,33 @@
+// Copyright Antony Polukhin, 2016-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_STACKTRACE_DETAIL_COLLECT_MSVC_IPP
+#define BOOST_STACKTRACE_DETAIL_COLLECT_MSVC_IPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/stacktrace/safe_dump_to.hpp>
+
+#include <boost/detail/winapi/stack_backtrace.hpp>
+
+namespace boost { namespace stacktrace { namespace detail {
+
+std::size_t this_thread_frames::collect(native_frame_ptr_t* out_frames, std::size_t max_frames_count, std::size_t skip) BOOST_NOEXCEPT {
+ return boost::detail::winapi::RtlCaptureStackBackTrace(
+ static_cast<boost::detail::winapi::ULONG_>(skip),
+ static_cast<boost::detail::winapi::ULONG_>(max_frames_count),
+ const_cast<boost::detail::winapi::PVOID_*>(out_frames),
+ 0
+ );
+}
+
+
+}}} // namespace boost::stacktrace
+
+#endif // BOOST_STACKTRACE_DETAIL_COLLECT_MSVC_IPP
diff --git a/boost/stacktrace/detail/collect_noop.ipp b/boost/stacktrace/detail/collect_noop.ipp
new file mode 100644
index 0000000000..bcfae4c400
--- /dev/null
+++ b/boost/stacktrace/detail/collect_noop.ipp
@@ -0,0 +1,25 @@
+// Copyright Antony Polukhin, 2016-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_STACKTRACE_DETAIL_COLLECT_NOOP_IPP
+#define BOOST_STACKTRACE_DETAIL_COLLECT_NOOP_IPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/stacktrace/safe_dump_to.hpp>
+
+namespace boost { namespace stacktrace { namespace detail {
+
+std::size_t this_thread_frames::collect(native_frame_ptr_t* /*out_frames*/, std::size_t /*max_frames_count*/, std::size_t /*skip*/) BOOST_NOEXCEPT {
+ return 0;
+}
+
+}}} // namespace boost::stacktrace::detail
+
+#endif // BOOST_STACKTRACE_DETAIL_COLLECT_NOOP_IPP
diff --git a/boost/stacktrace/detail/collect_unwind.ipp b/boost/stacktrace/detail/collect_unwind.ipp
new file mode 100644
index 0000000000..3ee4e8f61e
--- /dev/null
+++ b/boost/stacktrace/detail/collect_unwind.ipp
@@ -0,0 +1,68 @@
+// Copyright Antony Polukhin, 2016-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_STACKTRACE_DETAIL_COLLECT_UNWIND_IPP
+#define BOOST_STACKTRACE_DETAIL_COLLECT_UNWIND_IPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/stacktrace/safe_dump_to.hpp>
+
+#include <unwind.h>
+#include <cstdio>
+
+namespace boost { namespace stacktrace { namespace detail {
+
+struct unwind_state {
+ std::size_t frames_to_skip;
+ native_frame_ptr_t* current;
+ native_frame_ptr_t* end;
+};
+
+inline _Unwind_Reason_Code unwind_callback(::_Unwind_Context* context, void* arg) {
+ // Note: do not write `::_Unwind_GetIP` because it is a macro on some platforms.
+ // Use `_Unwind_GetIP` instead!
+ unwind_state* const state = static_cast<unwind_state*>(arg);
+ if (state->frames_to_skip) {
+ --state->frames_to_skip;
+ return _Unwind_GetIP(context) ? ::_URC_NO_REASON : ::_URC_END_OF_STACK;
+ }
+
+ *state->current = reinterpret_cast<native_frame_ptr_t>(
+ _Unwind_GetIP(context)
+ );
+
+ ++state->current;
+ if (!*(state->current - 1) || state->current == state->end) {
+ return ::_URC_END_OF_STACK;
+ }
+ return ::_URC_NO_REASON;
+}
+
+std::size_t this_thread_frames::collect(native_frame_ptr_t* out_frames, std::size_t max_frames_count, std::size_t skip) BOOST_NOEXCEPT {
+ std::size_t frames_count = 0;
+ if (!max_frames_count) {
+ return frames_count;
+ }
+
+ boost::stacktrace::detail::unwind_state state = { skip + 1, out_frames, out_frames + max_frames_count };
+ ::_Unwind_Backtrace(&boost::stacktrace::detail::unwind_callback, &state);
+ frames_count = state.current - out_frames;
+
+ if (frames_count && out_frames[frames_count - 1] == 0) {
+ -- frames_count;
+ }
+
+ return frames_count;
+}
+
+
+}}} // namespace boost::stacktrace::detail
+
+#endif // BOOST_STACKTRACE_DETAIL_COLLECT_UNWIND_IPP
diff --git a/boost/stacktrace/detail/frame_decl.hpp b/boost/stacktrace/detail/frame_decl.hpp
new file mode 100644
index 0000000000..10b912113f
--- /dev/null
+++ b/boost/stacktrace/detail/frame_decl.hpp
@@ -0,0 +1,159 @@
+// Copyright Antony Polukhin, 2016-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_STACKTRACE_DETAIL_FRAME_DECL_HPP
+#define BOOST_STACKTRACE_DETAIL_FRAME_DECL_HPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iosfwd>
+#include <string>
+
+#include <boost/core/explicit_operator_bool.hpp>
+
+#include <boost/stacktrace/safe_dump_to.hpp> // boost::stacktrace::detail::native_frame_ptr_t
+#include <boost/stacktrace/detail/void_ptr_cast.hpp>
+
+#include <boost/stacktrace/detail/push_options.pp>
+
+/// @file boost/stacktrace/detail/frame_decl.hpp
+/// Use <boost/stacktrace/frame.hpp> header instead of this one!
+
+namespace boost { namespace stacktrace {
+
+/// @class boost::stacktrace::frame boost/stacktrace/detail/frame_decl.hpp <boost/stacktrace/frame.hpp>
+/// @brief Class that stores frame/function address and can get information about it at runtime.
+class frame {
+public:
+ typedef boost::stacktrace::detail::native_frame_ptr_t native_frame_ptr_t;
+
+private:
+ /// @cond
+ native_frame_ptr_t addr_;
+ /// @endcond
+
+public:
+ /// @brief Constructs frame that references NULL address.
+ /// Calls to source_file() and source_line() will return empty string.
+ /// Calls to source_line() will return 0.
+ ///
+ /// @b Complexity: O(1).
+ ///
+ /// @b Async-Handler-Safety: Safe.
+ /// @throws Nothing.
+ BOOST_CONSTEXPR frame() BOOST_NOEXCEPT
+ : addr_(0)
+ {}
+
+#ifdef BOOST_STACKTRACE_DOXYGEN_INVOKED
+ /// @brief Copy constructs frame.
+ ///
+ /// @b Complexity: O(1).
+ ///
+ /// @b Async-Handler-Safety: Safe.
+ /// @throws Nothing.
+ constexpr frame(const frame&) = default;
+
+ /// @brief Copy assigns frame.
+ ///
+ /// @b Complexity: O(1).
+ ///
+ /// @b Async-Handler-Safety: Safe.
+ /// @throws Nothing.
+ constexpr frame& operator=(const frame&) = default;
+#endif
+
+ /// @brief Constructs frame that references addr and could later generate information about that address using platform specific features.
+ ///
+ /// @b Complexity: O(1).
+ ///
+ /// @b Async-Handler-Safety: Safe.
+ /// @throws Nothing.
+ BOOST_CONSTEXPR explicit frame(native_frame_ptr_t addr) BOOST_NOEXCEPT
+ : addr_(addr)
+ {}
+
+ /// @brief Constructs frame that references function_addr and could later generate information about that function using platform specific features.
+ ///
+ /// @b Complexity: O(1).
+ ///
+ /// @b Async-Handler-Safety: Safe.
+ /// @throws Nothing.
+ template <class T>
+ explicit frame(T* function_addr) BOOST_NOEXCEPT
+ : addr_(boost::stacktrace::detail::void_ptr_cast<native_frame_ptr_t>(function_addr))
+ {}
+
+ /// @returns Name of the frame (function name in a human readable form).
+ ///
+ /// @b Complexity: unknown (lots of platform specific work).
+ ///
+ /// @b Async-Handler-Safety: Unsafe.
+ /// @throws std::bad_alloc if not enough memory to construct resulting string.
+ BOOST_STACKTRACE_FUNCTION std::string name() const;
+
+ /// @returns Address of the frame function.
+ ///
+ /// @b Complexity: O(1).
+ ///
+ /// @b Async-Handler-Safety: Safe.
+ /// @throws Nothing.
+ BOOST_CONSTEXPR native_frame_ptr_t address() const BOOST_NOEXCEPT {
+ return addr_;
+ }
+
+ /// @returns Path to the source file, were the function of the frame is defined. Returns empty string
+ /// if this->source_line() == 0.
+ /// @throws std::bad_alloc if not enough memory to construct resulting string.
+ ///
+ /// @b Complexity: unknown (lots of platform specific work).
+ ///
+ /// @b Async-Handler-Safety: Unsafe.
+ BOOST_STACKTRACE_FUNCTION std::string source_file() const;
+
+ /// @returns Code line in the source file, were the function of the frame is defined.
+ /// @throws std::bad_alloc if not enough memory to construct string for internal needs.
+ ///
+ /// @b Complexity: unknown (lots of platform specific work).
+ ///
+ /// @b Async-Handler-Safety: Unsafe.
+ BOOST_STACKTRACE_FUNCTION std::size_t source_line() const;
+
+ /// @brief Checks that frame is not references NULL address.
+ /// @returns `true` if `this->address() != 0`
+ ///
+ /// @b Complexity: O(1)
+ ///
+ /// @b Async-Handler-Safety: Safe.
+ BOOST_EXPLICIT_OPERATOR_BOOL()
+
+ /// @brief Checks that frame references NULL address.
+ /// @returns `true` if `this->address() == 0`
+ ///
+ /// @b Complexity: O(1)
+ ///
+ /// @b Async-Handler-Safety: Safe.
+ BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT { return !address(); }
+
+ /// @cond
+ BOOST_CONSTEXPR bool operator!() const BOOST_NOEXCEPT { return !address(); }
+ /// @endcond
+};
+
+
+namespace detail {
+ BOOST_STACKTRACE_FUNCTION std::string to_string(const frame* frames, std::size_t size);
+} // namespace detail
+
+}} // namespace boost::stacktrace
+
+
+#include <boost/stacktrace/detail/pop_options.pp>
+
+#endif // BOOST_STACKTRACE_DETAIL_FRAME_DECL_HPP
diff --git a/boost/stacktrace/detail/frame_msvc.ipp b/boost/stacktrace/detail/frame_msvc.ipp
new file mode 100644
index 0000000000..6719598b33
--- /dev/null
+++ b/boost/stacktrace/detail/frame_msvc.ipp
@@ -0,0 +1,392 @@
+// Copyright Antony Polukhin, 2016-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_STACKTRACE_DETAIL_FRAME_MSVC_IPP
+#define BOOST_STACKTRACE_DETAIL_FRAME_MSVC_IPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/stacktrace/frame.hpp>
+
+#include <boost/core/demangle.hpp>
+#include <boost/core/noncopyable.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/stacktrace/detail/to_hex_array.hpp>
+#include <windows.h>
+#include "dbgeng.h"
+
+#include <boost/detail/winapi/get_current_process.hpp>
+
+#ifdef BOOST_MSVC
+# pragma comment(lib, "ole32.lib")
+# pragma comment(lib, "Dbgeng.lib")
+#endif
+
+
+#ifdef __CRT_UUID_DECL // for __MINGW32__
+ __CRT_UUID_DECL(IDebugClient,0x27fe5639,0x8407,0x4f47,0x83,0x64,0xee,0x11,0x8f,0xb0,0x8a,0xc8)
+ __CRT_UUID_DECL(IDebugControl,0x5182e668,0x105e,0x416e,0xad,0x92,0x24,0xef,0x80,0x04,0x24,0xba)
+ __CRT_UUID_DECL(IDebugSymbols,0x8c31e98c,0x983a,0x48a5,0x90,0x16,0x6f,0xe5,0xd6,0x67,0xa9,0x50)
+#elif defined(DEFINE_GUID) && !defined(BOOST_MSVC)
+ DEFINE_GUID(IID_IDebugClient,0x27fe5639,0x8407,0x4f47,0x83,0x64,0xee,0x11,0x8f,0xb0,0x8a,0xc8);
+ DEFINE_GUID(IID_IDebugControl,0x5182e668,0x105e,0x416e,0xad,0x92,0x24,0xef,0x80,0x04,0x24,0xba);
+ DEFINE_GUID(IID_IDebugSymbols,0x8c31e98c,0x983a,0x48a5,0x90,0x16,0x6f,0xe5,0xd6,0x67,0xa9,0x50);
+#endif
+
+
+
+// Testing. Remove later
+//# define __uuidof(x) ::IID_ ## x
+
+namespace boost { namespace stacktrace { namespace detail {
+
+class com_global_initer: boost::noncopyable {
+ bool ok_;
+
+public:
+ com_global_initer() BOOST_NOEXCEPT
+ : ok_(false)
+ {
+ // COINIT_MULTITHREADED means that we must serialize access to the objects manually.
+ // This is the fastest way to work. If user calls CoInitializeEx before us - we
+ // can end up with other mode (which is OK for us).
+ //
+ // If we call CoInitializeEx befire user - user may end up with different mode, which is a problem.
+ // So we need to call that initialization function as late as possible.
+ const boost::detail::winapi::DWORD_ res = ::CoInitializeEx(0, COINIT_MULTITHREADED);
+ ok_ = (res == S_OK || res == S_FALSE);
+ }
+
+ ~com_global_initer() BOOST_NOEXCEPT {
+ if (ok_) {
+ ::CoUninitialize();
+ }
+ }
+};
+
+
+template <class T>
+class com_holder: boost::noncopyable {
+ T* holder_;
+
+public:
+ com_holder(const com_global_initer&) BOOST_NOEXCEPT
+ : holder_(0)
+ {}
+
+ T* operator->() const BOOST_NOEXCEPT {
+ return holder_;
+ }
+
+ void** to_void_ptr_ptr() BOOST_NOEXCEPT {
+ return reinterpret_cast<void**>(&holder_);
+ }
+
+ bool is_inited() const BOOST_NOEXCEPT {
+ return !!holder_;
+ }
+
+ ~com_holder() BOOST_NOEXCEPT {
+ if (holder_) {
+ holder_->Release();
+ }
+ }
+};
+
+
+static std::string minwg_demangling_workaround(const std::string& s) {
+#ifdef BOOST_GCC
+ if (s.empty()) {
+ return s;
+ }
+
+ if (s[0] != '_') {
+ return boost::core::demangle(('_' + s).c_str());
+ }
+
+ return boost::core::demangle(s.c_str());
+#else
+ return s;
+#endif
+}
+
+class debugging_symbols: boost::noncopyable {
+ static void try_init_com(com_holder< ::IDebugSymbols>& idebug, const com_global_initer& com) BOOST_NOEXCEPT {
+ com_holder< ::IDebugClient> iclient(com);
+ if (S_OK != ::DebugCreate(__uuidof(IDebugClient), iclient.to_void_ptr_ptr())) {
+ return;
+ }
+
+ com_holder< ::IDebugControl> icontrol(com);
+ const bool res0 = (S_OK == iclient->QueryInterface(
+ __uuidof(IDebugControl),
+ icontrol.to_void_ptr_ptr()
+ ));
+ if (!res0) {
+ return;
+ }
+
+ const bool res1 = (S_OK == iclient->AttachProcess(
+ 0,
+ ::GetCurrentProcessId(),
+ DEBUG_ATTACH_NONINVASIVE | DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND
+ ));
+ if (!res1) {
+ return;
+ }
+
+ if (S_OK != icontrol->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE)) {
+ return;
+ }
+
+ // No cheking: QueryInterface sets the output parameter to NULL in case of error.
+ iclient->QueryInterface(__uuidof(IDebugSymbols), idebug.to_void_ptr_ptr());
+ }
+
+#ifndef BOOST_STACKTRACE_USE_WINDBG_CACHED
+
+ boost::stacktrace::detail::com_global_initer com_;
+ com_holder< ::IDebugSymbols> idebug_;
+public:
+ debugging_symbols() BOOST_NOEXCEPT
+ : com_()
+ , idebug_(com_)
+ {
+ try_init_com(idebug_, com_);
+ }
+
+#else
+
+#ifdef BOOST_NO_CXX11_THREAD_LOCAL
+# error Your compiler does not support C++11 thread_local storage. It's impossible to build with BOOST_STACKTRACE_USE_WINDBG_CACHED.
+#endif
+
+ static com_holder< ::IDebugSymbols>& get_thread_local_debug_inst() BOOST_NOEXCEPT {
+ // [class.mfct]: A static local variable or local type in a member function always refers to the same entity, whether
+ // or not the member function is inline.
+ static thread_local boost::stacktrace::detail::com_global_initer com;
+ static thread_local com_holder< ::IDebugSymbols> idebug(com);
+
+ if (!idebug.is_inited()) {
+ try_init_com(idebug, com);
+ }
+
+ return idebug;
+ }
+
+ com_holder< ::IDebugSymbols>& idebug_;
+public:
+ debugging_symbols() BOOST_NOEXCEPT
+ : idebug_( get_thread_local_debug_inst() )
+ {}
+
+#endif // #ifndef BOOST_STACKTRACE_USE_WINDBG_CACHED
+
+ bool is_inited() const BOOST_NOEXCEPT {
+ return idebug_.is_inited();
+ }
+
+ std::string get_name_impl(const void* addr, std::string* module_name = 0) const {
+ std::string result;
+ if (!is_inited()) {
+ return result;
+ }
+ const ULONG64 offset = reinterpret_cast<ULONG64>(addr);
+
+ char name[256];
+ name[0] = '\0';
+ ULONG size = 0;
+ bool res = (S_OK == idebug_->GetNameByOffset(
+ offset,
+ name,
+ sizeof(name),
+ &size,
+ 0
+ ));
+
+ if (!res && size != 0) {
+ result.resize(size);
+ res = (S_OK == idebug_->GetNameByOffset(
+ offset,
+ &result[0],
+ static_cast<ULONG>(result.size()),
+ &size,
+ 0
+ ));
+ } else if (res) {
+ result = name;
+ }
+
+ if (!res) {
+ result.clear();
+ return result;
+ }
+
+ const std::size_t delimiter = result.find_first_of('!');
+ if (module_name) {
+ *module_name = result.substr(0, delimiter);
+ }
+
+ if (delimiter == std::string::npos) {
+ // If 'delimiter' is equal to 'std::string::npos' then we have only module name.
+ result.clear();
+ return result;
+ }
+
+ result = minwg_demangling_workaround(
+ result.substr(delimiter + 1)
+ );
+
+ return result;
+ }
+
+ std::size_t get_line_impl(const void* addr) const BOOST_NOEXCEPT {
+ ULONG result = 0;
+ if (!is_inited()) {
+ return result;
+ }
+
+ const bool is_ok = (S_OK == idebug_->GetLineByOffset(
+ reinterpret_cast<ULONG64>(addr),
+ &result,
+ 0,
+ 0,
+ 0,
+ 0
+ ));
+
+ return (is_ok ? result : 0);
+ }
+
+ std::pair<std::string, std::size_t> get_source_file_line_impl(const void* addr) const {
+ std::pair<std::string, std::size_t> result;
+ if (!is_inited()) {
+ return result;
+ }
+ const ULONG64 offset = reinterpret_cast<ULONG64>(addr);
+
+ char name[256];
+ name[0] = 0;
+ ULONG size = 0;
+ ULONG line_num = 0;
+ bool res = (S_OK == idebug_->GetLineByOffset(
+ offset,
+ &line_num,
+ name,
+ sizeof(name),
+ &size,
+ 0
+ ));
+
+ if (res) {
+ result.first = name;
+ result.second = line_num;
+ return result;
+ }
+
+ if (!res && size == 0) {
+ return result;
+ }
+
+ result.first.resize(size);
+ res = (S_OK == idebug_->GetLineByOffset(
+ offset,
+ &line_num,
+ &result.first[0],
+ static_cast<ULONG>(result.first.size()),
+ &size,
+ 0
+ ));
+ result.second = line_num;
+
+ if (!res) {
+ result.first.clear();
+ result.second = 0;
+ }
+
+ return result;
+ }
+
+ void to_string_impl(const void* addr, std::string& res) const {
+ if (!is_inited()) {
+ return;
+ }
+
+ std::string module_name;
+ std::string name = this->get_name_impl(addr, &module_name);
+ if (!name.empty()) {
+ res += name;
+ } else {
+ res += to_hex_array(addr).data();
+ }
+
+ std::pair<std::string, std::size_t> source_line = this->get_source_file_line_impl(addr);
+ if (!source_line.first.empty() && source_line.second) {
+ res += " at ";
+ res += source_line.first;
+ res += ':';
+ res += boost::lexical_cast<boost::array<char, 40> >(source_line.second).data();
+ } else if (!module_name.empty()) {
+ res += " in ";
+ res += module_name;
+ }
+ }
+};
+
+std::string to_string(const frame* frames, std::size_t size) {
+ boost::stacktrace::detail::debugging_symbols idebug;
+ if (!idebug.is_inited()) {
+ return std::string();
+ }
+
+ std::string res;
+ res.reserve(64 * size);
+ for (std::size_t i = 0; i < size; ++i) {
+ if (i < 10) {
+ res += ' ';
+ }
+ res += boost::lexical_cast<boost::array<char, 40> >(i).data();
+ res += '#';
+ res += ' ';
+ idebug.to_string_impl(frames[i].address(), res);
+ res += '\n';
+ }
+
+ return res;
+}
+
+} // namespace detail
+
+std::string frame::name() const {
+ boost::stacktrace::detail::debugging_symbols idebug;
+ return idebug.get_name_impl(addr_);
+}
+
+
+std::string frame::source_file() const {
+ boost::stacktrace::detail::debugging_symbols idebug;
+ return idebug.get_source_file_line_impl(addr_).first;
+}
+
+std::size_t frame::source_line() const {
+ boost::stacktrace::detail::debugging_symbols idebug;
+ return idebug.get_line_impl(addr_);
+}
+
+std::string to_string(const frame& f) {
+ std::string res;
+
+ boost::stacktrace::detail::debugging_symbols idebug;
+ idebug.to_string_impl(f.address(), res);
+ return res;
+}
+
+}} // namespace boost::stacktrace
+
+#endif // BOOST_STACKTRACE_DETAIL_FRAME_MSVC_IPP
diff --git a/boost/stacktrace/detail/frame_noop.ipp b/boost/stacktrace/detail/frame_noop.ipp
new file mode 100644
index 0000000000..b9b1b98800
--- /dev/null
+++ b/boost/stacktrace/detail/frame_noop.ipp
@@ -0,0 +1,44 @@
+// Copyright Antony Polukhin, 2016-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_STACKTRACE_DETAIL_FRAME_NOOP_IPP
+#define BOOST_STACKTRACE_DETAIL_FRAME_NOOP_IPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/stacktrace/frame.hpp>
+
+namespace boost { namespace stacktrace { namespace detail {
+
+std::string to_string(const frame* /*frames*/, std::size_t /*count*/) {
+ return std::string();
+}
+
+} // namespace detail
+
+std::string frame::name() const {
+ return std::string();
+}
+
+std::string frame::source_file() const {
+ return std::string();
+}
+
+std::size_t frame::source_line() const {
+ return 0;
+}
+
+std::string to_string(const frame& /*f*/) {
+ return std::string();
+}
+
+
+}} // namespace boost::stacktrace
+
+#endif // BOOST_STACKTRACE_DETAIL_FRAME_NOOP_IPP
diff --git a/boost/stacktrace/detail/frame_unwind.ipp b/boost/stacktrace/detail/frame_unwind.ipp
new file mode 100644
index 0000000000..d4e7973968
--- /dev/null
+++ b/boost/stacktrace/detail/frame_unwind.ipp
@@ -0,0 +1,103 @@
+// Copyright Antony Polukhin, 2016-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_STACKTRACE_DETAIL_FRAME_UNWIND_IPP
+#define BOOST_STACKTRACE_DETAIL_FRAME_UNWIND_IPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/stacktrace/frame.hpp>
+
+#include <boost/stacktrace/detail/to_hex_array.hpp>
+#include <boost/stacktrace/detail/location_from_symbol.hpp>
+#include <boost/core/demangle.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include <cstdio>
+
+#ifdef BOOST_STACKTRACE_USE_BACKTRACE
+# include <boost/stacktrace/detail/libbacktrace_impls.hpp>
+#elif defined(BOOST_STACKTRACE_USE_ADDR2LINE)
+# include <boost/stacktrace/detail/addr2line_impls.hpp>
+#else
+# include <boost/stacktrace/detail/unwind_base_impls.hpp>
+#endif
+
+namespace boost { namespace stacktrace { namespace detail {
+
+template <class Base>
+class to_string_impl_base: private Base {
+public:
+ std::string operator()(boost::stacktrace::detail::native_frame_ptr_t addr) {
+ Base::res.clear();
+ Base::prepare_function_name(addr);
+ if (!Base::res.empty()) {
+ Base::res = boost::core::demangle(Base::res.c_str());
+ } else {
+ Base::res = to_hex_array(addr).data();
+ }
+
+ if (Base::prepare_source_location(addr)) {
+ return Base::res;
+ }
+
+ boost::stacktrace::detail::location_from_symbol loc(addr);
+ if (!loc.empty()) {
+ Base::res += " in ";
+ Base::res += loc.name();
+ }
+
+ return Base::res;
+ }
+};
+
+std::string to_string(const frame* frames, std::size_t size) {
+ std::string res;
+ res.reserve(64 * size);
+
+ to_string_impl impl;
+
+ for (std::size_t i = 0; i < size; ++i) {
+ if (i < 10) {
+ res += ' ';
+ }
+ res += boost::lexical_cast<boost::array<char, 40> >(i).data();
+ res += '#';
+ res += ' ';
+ res += impl(frames[i].address());
+ res += '\n';
+ }
+
+ return res;
+}
+
+
+} // namespace detail
+
+
+std::string frame::name() const {
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+ ::Dl_info dli;
+ const bool dl_ok = !!::dladdr(addr_, &dli);
+ if (dl_ok && dli.dli_sname) {
+ return boost::core::demangle(dli.dli_sname);
+ }
+#endif
+ return boost::stacktrace::detail::name_impl(addr_);
+}
+
+std::string to_string(const frame& f) {
+ boost::stacktrace::detail::to_string_impl impl;
+ return impl(f.address());
+}
+
+
+}} // namespace boost::stacktrace
+
+#endif // BOOST_STACKTRACE_DETAIL_FRAME_UNWIND_IPP
diff --git a/boost/stacktrace/detail/libbacktrace_impls.hpp b/boost/stacktrace/detail/libbacktrace_impls.hpp
new file mode 100644
index 0000000000..a0c2d2a5aa
--- /dev/null
+++ b/boost/stacktrace/detail/libbacktrace_impls.hpp
@@ -0,0 +1,173 @@
+// Copyright Antony Polukhin, 2016-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_STACKTRACE_DETAIL_LIBBACKTRACE_IMPLS_HPP
+#define BOOST_STACKTRACE_DETAIL_LIBBACKTRACE_IMPLS_HPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/stacktrace/detail/to_hex_array.hpp>
+#include <boost/core/demangle.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include <backtrace.h>
+
+namespace boost { namespace stacktrace { namespace detail {
+
+
+struct pc_data {
+ std::string* function;
+ std::string* filename;
+ std::size_t line;
+};
+
+inline int libbacktrace_full_callback(void *data, uintptr_t /*pc*/, const char *filename, int lineno, const char *function) {
+ pc_data& d = *static_cast<pc_data*>(data);
+ if (d.filename && filename) {
+ *d.filename = filename;
+ }
+ if (d.function && function) {
+ *d.function = function;
+ }
+ d.line = lineno;
+ return 0;
+}
+
+inline void libbacktrace_error_callback(void* /*data*/, const char* /*msg*/, int /*errnum*/) BOOST_NOEXCEPT {
+ // Do nothing, just return.
+}
+
+
+extern inline ::backtrace_state* construct_state() BOOST_NOEXCEPT {
+ return ::backtrace_create_state(
+ 0, 0 /*thread-safe*/, boost::stacktrace::detail::libbacktrace_error_callback, 0
+ );
+
+ // TODO: this does not seem to work well when this function is in .so:
+ // Not async-signal-safe, so this method is not called from async-safe functions.
+ //
+ // This function is not async signal safe because:
+ // * Dynamic initialization of a block-scope variable with static storage duration could lock a mutex
+ // * No guarantees on `backtrace_create_state` function.
+
+ // [dcl.inline]: A static local variable in an inline function with external linkage always refers to the same object.
+
+ /*
+ static ::backtrace_state* state = ::backtrace_create_state(
+ 0, 1 , boost::stacktrace::detail::libbacktrace_error_callback, 0
+ );
+
+ return state;
+ */
+}
+
+struct to_string_using_backtrace {
+ std::string res;
+ ::backtrace_state* state;
+ std::string filename;
+ std::size_t line;
+
+ void prepare_function_name(const void* addr) {
+ boost::stacktrace::detail::pc_data data = {&res, &filename, 0};
+ if (state) {
+ ::backtrace_pcinfo(
+ state,
+ reinterpret_cast<uintptr_t>(addr),
+ boost::stacktrace::detail::libbacktrace_full_callback,
+ boost::stacktrace::detail::libbacktrace_error_callback,
+ &data
+ );
+ }
+ line = data.line;
+ }
+
+ bool prepare_source_location(const void* /*addr*/) {
+ if (filename.empty() || !line) {
+ return false;
+ }
+
+ res += " at ";
+ res += filename;
+ res += ':';
+ res += boost::lexical_cast<boost::array<char, 40> >(line).data();
+ return true;
+ }
+
+ to_string_using_backtrace() BOOST_NOEXCEPT {
+ state = boost::stacktrace::detail::construct_state();
+ }
+};
+
+template <class Base> class to_string_impl_base;
+typedef to_string_impl_base<to_string_using_backtrace> to_string_impl;
+
+inline std::string name_impl(const void* addr) {
+ std::string res;
+
+ ::backtrace_state* state = boost::stacktrace::detail::construct_state();
+
+ boost::stacktrace::detail::pc_data data = {&res, 0, 0};
+ if (state) {
+ ::backtrace_pcinfo(
+ state,
+ reinterpret_cast<uintptr_t>(addr),
+ boost::stacktrace::detail::libbacktrace_full_callback,
+ boost::stacktrace::detail::libbacktrace_error_callback,
+ &data
+ );
+ }
+ if (!res.empty()) {
+ res = boost::core::demangle(res.c_str());
+ }
+
+ return res;
+}
+
+} // namespace detail
+
+std::string frame::source_file() const {
+ std::string res;
+
+ ::backtrace_state* state = boost::stacktrace::detail::construct_state();
+
+ boost::stacktrace::detail::pc_data data = {0, &res, 0};
+ if (state) {
+ ::backtrace_pcinfo(
+ state,
+ reinterpret_cast<uintptr_t>(addr_),
+ boost::stacktrace::detail::libbacktrace_full_callback,
+ boost::stacktrace::detail::libbacktrace_error_callback,
+ &data
+ );
+ }
+
+ return res;
+}
+
+std::size_t frame::source_line() const {
+ ::backtrace_state* state = boost::stacktrace::detail::construct_state();
+
+ boost::stacktrace::detail::pc_data data = {0, 0, 0};
+ if (state) {
+ ::backtrace_pcinfo(
+ state,
+ reinterpret_cast<uintptr_t>(addr_),
+ boost::stacktrace::detail::libbacktrace_full_callback,
+ boost::stacktrace::detail::libbacktrace_error_callback,
+ &data
+ );
+ }
+
+ return data.line;
+}
+
+
+}} // namespace boost::stacktrace
+
+#endif // BOOST_STACKTRACE_DETAIL_LIBBACKTRACE_IMPLS_HPP
diff --git a/boost/stacktrace/detail/location_from_symbol.hpp b/boost/stacktrace/detail/location_from_symbol.hpp
new file mode 100644
index 0000000000..d20b0d6707
--- /dev/null
+++ b/boost/stacktrace/detail/location_from_symbol.hpp
@@ -0,0 +1,76 @@
+// Copyright Antony Polukhin, 2016-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_STACKTRACE_DETAIL_LOCATION_FROM_SYMBOL_HPP
+#define BOOST_STACKTRACE_DETAIL_LOCATION_FROM_SYMBOL_HPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+# include <dlfcn.h>
+#else
+# include <boost/detail/winapi/dll.hpp>
+#endif
+
+namespace boost { namespace stacktrace { namespace detail {
+
+class location_from_symbol {
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+ ::Dl_info dli_;
+
+public:
+ explicit location_from_symbol(const void* addr) BOOST_NOEXCEPT
+ : dli_()
+ {
+ if (!::dladdr(addr, &dli_)) {
+ dli_.dli_fname = 0;
+ }
+ }
+
+ bool empty() const BOOST_NOEXCEPT {
+ return !dli_.dli_fname;
+ }
+
+ const char* name() const BOOST_NOEXCEPT {
+ return dli_.dli_fname;
+ }
+#else
+ BOOST_STATIC_CONSTEXPR boost::detail::winapi::DWORD_ DEFAULT_PATH_SIZE_ = 260;
+
+ char file_name_[DEFAULT_PATH_SIZE_];
+
+public:
+ explicit location_from_symbol(const void* addr) BOOST_NOEXCEPT {
+ file_name_[0] = '\0';
+
+ boost::detail::winapi::MEMORY_BASIC_INFORMATION_ mbi;
+ if (!boost::detail::winapi::VirtualQuery(addr, &mbi, sizeof(mbi))) {
+ return;
+ }
+
+ boost::detail::winapi::HMODULE_ handle = reinterpret_cast<boost::detail::winapi::HMODULE_>(mbi.AllocationBase);
+ if (!boost::detail::winapi::GetModuleFileNameA(handle, file_name_, DEFAULT_PATH_SIZE_)) {
+ file_name_[0] = '\0';
+ return;
+ }
+ }
+
+ bool empty() const BOOST_NOEXCEPT {
+ return file_name_[0] == '\0';
+ }
+
+ const char* name() const BOOST_NOEXCEPT {
+ return file_name_;
+ }
+#endif
+};
+
+}}} // namespace boost::stacktrace::detail
+
+#endif // BOOST_STACKTRACE_DETAIL_LOCATION_FROM_SYMBOL_HPP
diff --git a/boost/stacktrace/detail/pop_options.pp b/boost/stacktrace/detail/pop_options.pp
new file mode 100644
index 0000000000..8995b00ada
--- /dev/null
+++ b/boost/stacktrace/detail/pop_options.pp
@@ -0,0 +1,12 @@
+// Copyright Antony Polukhin, 2016-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)
+
+// No include guards! Intentionally.
+
+#ifdef BOOST_STACKTRACE_FUNCTION
+# undef BOOST_STACKTRACE_FUNCTION
+#endif
+
diff --git a/boost/stacktrace/detail/push_options.pp b/boost/stacktrace/detail/push_options.pp
new file mode 100644
index 0000000000..3adb626121
--- /dev/null
+++ b/boost/stacktrace/detail/push_options.pp
@@ -0,0 +1,31 @@
+// Copyright Antony Polukhin, 2016-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)
+
+// No include guards! Intentionally.
+
+// Link or header only
+#if !defined(BOOST_STACKTRACE_LINK) && defined(BOOST_STACKTRACE_DYN_LINK)
+# define BOOST_STACKTRACE_LINK
+#endif
+
+#if defined(BOOST_STACKTRACE_LINK) && !defined(BOOST_STACKTRACE_DYN_LINK) && defined(BOOST_ALL_DYN_LINK)
+# define BOOST_STACKTRACE_DYN_LINK
+#endif
+
+#ifdef BOOST_STACKTRACE_LINK
+# if defined(BOOST_STACKTRACE_DYN_LINK)
+# ifdef BOOST_STACKTRACE_INTERNAL_BUILD_LIBS
+# define BOOST_STACKTRACE_FUNCTION BOOST_SYMBOL_EXPORT
+# else
+# define BOOST_STACKTRACE_FUNCTION BOOST_SYMBOL_IMPORT
+# endif
+# else
+# define BOOST_STACKTRACE_FUNCTION
+# endif
+#elif !defined(BOOST_STACKTRACE_DOXYGEN_INVOKED)
+# define BOOST_STACKTRACE_FUNCTION inline
+#endif
+
diff --git a/boost/stacktrace/detail/safe_dump_noop.ipp b/boost/stacktrace/detail/safe_dump_noop.ipp
new file mode 100644
index 0000000000..78fdc3a8ae
--- /dev/null
+++ b/boost/stacktrace/detail/safe_dump_noop.ipp
@@ -0,0 +1,37 @@
+// Copyright Antony Polukhin, 2016-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_STACKTRACE_DETAIL_SAFE_DUMP_NOOP_IPP
+#define BOOST_STACKTRACE_DETAIL_SAFE_DUMP_NOOP_IPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/stacktrace/safe_dump_to.hpp>
+
+namespace boost { namespace stacktrace { namespace detail {
+
+
+#if defined(BOOST_WINDOWS)
+std::size_t dump(void* /*fd*/, const native_frame_ptr_t* /*frames*/, std::size_t /*frames_count*/) BOOST_NOEXCEPT {
+ return 0;
+}
+#else
+std::size_t dump(int /*fd*/, const native_frame_ptr_t* /*frames*/, std::size_t /*frames_count*/) BOOST_NOEXCEPT {
+ return 0;
+}
+#endif
+
+
+std::size_t dump(const char* /*file*/, const native_frame_ptr_t* /*frames*/, std::size_t /*frames_count*/) BOOST_NOEXCEPT {
+ return 0;
+}
+
+}}} // namespace boost::stacktrace::detail
+
+#endif // BOOST_STACKTRACE_DETAIL_SAFE_DUMP_NOOP_IPP
diff --git a/boost/stacktrace/detail/safe_dump_posix.ipp b/boost/stacktrace/detail/safe_dump_posix.ipp
new file mode 100644
index 0000000000..37eef5ac7c
--- /dev/null
+++ b/boost/stacktrace/detail/safe_dump_posix.ipp
@@ -0,0 +1,58 @@
+// Copyright Antony Polukhin, 2016-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_STACKTRACE_DETAIL_SAFE_DUMP_POSIX_IPP
+#define BOOST_STACKTRACE_DETAIL_SAFE_DUMP_POSIX_IPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/stacktrace/safe_dump_to.hpp>
+
+#include <unistd.h> // ::write
+#include <fcntl.h> // ::open
+
+
+namespace boost { namespace stacktrace { namespace detail {
+
+std::size_t dump(int fd, const native_frame_ptr_t* frames, std::size_t frames_count) BOOST_NOEXCEPT {
+ // We do not retry, because this function must be typically called from signal handler so it's:
+ // * to scary to continue in case of EINTR
+ // * EAGAIN or EWOULDBLOCK may occur only in case of O_NONBLOCK is set for fd,
+ // so it seems that user does not want to block
+ if (::write(fd, frames, sizeof(native_frame_ptr_t) * frames_count) == -1) {
+ return 0;
+ }
+
+ return frames_count;
+}
+
+std::size_t dump(const char* file, const native_frame_ptr_t* frames, std::size_t frames_count) BOOST_NOEXCEPT {
+ const int fd = ::open(
+ file,
+ O_CREAT | O_WRONLY | O_TRUNC,
+#if defined(S_IWUSR) && defined(S_IRUSR) // Workarounds for some Android OSes
+ S_IWUSR | S_IRUSR
+#elif defined(S_IWRITE) && defined(S_IREAD)
+ S_IWRITE | S_IREAD
+#else
+ 0
+#endif
+ );
+ if (fd == -1) {
+ return 0;
+ }
+
+ const std::size_t size = boost::stacktrace::detail::dump(fd, frames, frames_count);
+ ::close(fd);
+ return size;
+}
+
+}}} // namespace boost::stacktrace::detail
+
+#endif // BOOST_STACKTRACE_DETAIL_SAFE_DUMP_POSIX_IPP
diff --git a/boost/stacktrace/detail/safe_dump_win.ipp b/boost/stacktrace/detail/safe_dump_win.ipp
new file mode 100644
index 0000000000..26f0516c01
--- /dev/null
+++ b/boost/stacktrace/detail/safe_dump_win.ipp
@@ -0,0 +1,60 @@
+// Copyright Antony Polukhin, 2016-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_STACKTRACE_DETAIL_SAFE_DUMP_WIN_IPP
+#define BOOST_STACKTRACE_DETAIL_SAFE_DUMP_WIN_IPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/stacktrace/safe_dump_to.hpp>
+
+#include <boost/core/noncopyable.hpp>
+
+#include <boost/detail/winapi/get_current_process.hpp>
+#include <boost/detail/winapi/file_management.hpp>
+#include <boost/detail/winapi/handles.hpp>
+#include <boost/detail/winapi/access_rights.hpp>
+
+namespace boost { namespace stacktrace { namespace detail {
+
+std::size_t dump(void* fd, const native_frame_ptr_t* frames, std::size_t frames_count) BOOST_NOEXCEPT {
+ boost::detail::winapi::DWORD_ written;
+ const boost::detail::winapi::DWORD_ bytes_to_write = static_cast<boost::detail::winapi::DWORD_>(
+ sizeof(native_frame_ptr_t) * frames_count
+ );
+ if (!boost::detail::winapi::WriteFile(fd, frames, bytes_to_write, &written, 0)) {
+ return 0;
+ }
+
+ return frames_count;
+}
+
+std::size_t dump(const char* file, const native_frame_ptr_t* frames, std::size_t frames_count) BOOST_NOEXCEPT {
+ void* const fd = boost::detail::winapi::CreateFileA(
+ file,
+ boost::detail::winapi::GENERIC_WRITE_,
+ 0,
+ 0,
+ boost::detail::winapi::CREATE_ALWAYS_,
+ boost::detail::winapi::FILE_ATTRIBUTE_NORMAL_,
+ 0
+ );
+
+ if (fd == boost::detail::winapi::invalid_handle_value) {
+ return 0;
+ }
+
+ const std::size_t size = boost::stacktrace::detail::dump(fd, frames, frames_count);
+ boost::detail::winapi::CloseHandle(fd);
+ return size;
+}
+
+}}} // namespace boost::stacktrace::detail
+
+#endif // BOOST_STACKTRACE_DETAIL_SAFE_DUMP_WIN_IPP
diff --git a/boost/stacktrace/detail/to_hex_array.hpp b/boost/stacktrace/detail/to_hex_array.hpp
new file mode 100644
index 0000000000..dd55ded8b6
--- /dev/null
+++ b/boost/stacktrace/detail/to_hex_array.hpp
@@ -0,0 +1,54 @@
+// Copyright Antony Polukhin, 2016-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_STACKTRACE_DETAIL_TO_HEX_ARRAY_HPP
+#define BOOST_STACKTRACE_DETAIL_TO_HEX_ARRAY_HPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/array.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/type_traits/make_unsigned.hpp>
+
+namespace boost { namespace stacktrace { namespace detail {
+
+BOOST_STATIC_CONSTEXPR char to_hex_array_bytes[] = "0123456789ABCDEF";
+
+template <class T>
+inline boost::array<char, 2 + sizeof(void*) * 2 + 1> to_hex_array(T addr) BOOST_NOEXCEPT {
+ boost::array<char, 2 + sizeof(void*) * 2 + 1> ret = {"0x"};
+ ret.back() = '\0';
+ BOOST_STATIC_ASSERT_MSG(!boost::is_pointer<T>::value, "");
+
+ const std::size_t s = sizeof(T);
+
+ char* out = ret.data() + s * 2 + 1;
+
+ for (std::size_t i = 0; i < s; ++i) {
+ const unsigned char tmp_addr = (addr & 0xFFu);
+ *out = to_hex_array_bytes[tmp_addr & 0xF];
+ -- out;
+ *out = to_hex_array_bytes[tmp_addr >> 4];
+ -- out;
+ addr >>= 8;
+ }
+
+ return ret;
+}
+
+inline boost::array<char, 2 + sizeof(void*) * 2 + 1> to_hex_array(const void* addr) BOOST_NOEXCEPT {
+ return to_hex_array(
+ reinterpret_cast< boost::make_unsigned<std::ptrdiff_t>::type >(addr)
+ );
+}
+
+}}} // namespace boost::stacktrace::detail
+
+#endif // BOOST_STACKTRACE_DETAIL_TO_HEX_ARRAY_HPP
diff --git a/boost/stacktrace/detail/unwind_base_impls.hpp b/boost/stacktrace/detail/unwind_base_impls.hpp
new file mode 100644
index 0000000000..18a2378d25
--- /dev/null
+++ b/boost/stacktrace/detail/unwind_base_impls.hpp
@@ -0,0 +1,50 @@
+// Copyright Antony Polukhin, 2016-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_STACKTRACE_DETAIL_UNWIND_BASE_IMPLS_HPP
+#define BOOST_STACKTRACE_DETAIL_UNWIND_BASE_IMPLS_HPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/stacktrace/frame.hpp>
+
+namespace boost { namespace stacktrace { namespace detail {
+
+struct to_string_using_nothing {
+ std::string res;
+
+ void prepare_function_name(const void* addr) {
+ res = boost::stacktrace::frame(addr).name();
+ }
+
+ bool prepare_source_location(const void* /*addr*/) const BOOST_NOEXCEPT {
+ return false;
+ }
+};
+
+template <class Base> class to_string_impl_base;
+typedef to_string_impl_base<to_string_using_nothing> to_string_impl;
+
+inline std::string name_impl(const void* /*addr*/) {
+ return std::string();
+}
+
+} // namespace detail
+
+std::string frame::source_file() const {
+ return std::string();
+}
+
+std::size_t frame::source_line() const {
+ return 0;
+}
+
+}} // namespace boost::stacktrace
+
+#endif // BOOST_STACKTRACE_DETAIL_UNWIND_BASE_IMPLS_HPP
diff --git a/boost/stacktrace/detail/void_ptr_cast.hpp b/boost/stacktrace/detail/void_ptr_cast.hpp
new file mode 100644
index 0000000000..f956f4789f
--- /dev/null
+++ b/boost/stacktrace/detail/void_ptr_cast.hpp
@@ -0,0 +1,46 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015-2017 Antony Polukhin.
+//
+// Distributed under the 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_STACKTRACE_DETAIL_VOID_PTR_CAST_HPP
+#define BOOST_STACKTRACE_DETAIL_VOID_PTR_CAST_HPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+
+#if defined(__GNUC__) && defined(__GNUC_MINOR__) && (__GNUC__ * 100 + __GNUC_MINOR__ > 301)
+# pragma GCC system_header
+#endif
+
+namespace boost { namespace stacktrace { namespace detail {
+
+// GCC warns when reinterpret_cast between function pointer and object pointer occur.
+// This functionsuppress the warnings and ensures that such casts are safe.
+template <class To, class From>
+To void_ptr_cast(From* v) BOOST_NOEXCEPT {
+ BOOST_STATIC_ASSERT_MSG(
+ boost::is_pointer<To>::value,
+ "`void_ptr_cast` function must be used only for casting to or from void pointers."
+ );
+
+ BOOST_STATIC_ASSERT_MSG(
+ sizeof(From*) == sizeof(To),
+ "Pointer to function and pointer to object differ in size on your platform."
+ );
+
+ return reinterpret_cast<To>(v);
+}
+
+
+}}} // boost::stacktrace::detail
+
+#endif // BOOST_STACKTRACE_DETAIL_VOID_PTR_CAST_HPP
+
diff --git a/boost/stacktrace/frame.hpp b/boost/stacktrace/frame.hpp
new file mode 100644
index 0000000000..4ad3c507f3
--- /dev/null
+++ b/boost/stacktrace/frame.hpp
@@ -0,0 +1,67 @@
+// Copyright Antony Polukhin, 2016-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_STACKTRACE_FRAME_HPP
+#define BOOST_STACKTRACE_FRAME_HPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iosfwd>
+#include <string>
+
+#include <boost/core/explicit_operator_bool.hpp>
+
+#include <boost/stacktrace/safe_dump_to.hpp> // boost::stacktrace::detail::native_frame_ptr_t
+
+#include <boost/stacktrace/detail/frame_decl.hpp>
+#include <boost/stacktrace/detail/push_options.pp>
+
+namespace boost { namespace stacktrace {
+
+/// Comparison operators that provide platform dependant ordering and have O(1) complexity; are Async-Handler-Safe.
+BOOST_CONSTEXPR inline bool operator< (const frame& lhs, const frame& rhs) BOOST_NOEXCEPT { return lhs.address() < rhs.address(); }
+BOOST_CONSTEXPR inline bool operator> (const frame& lhs, const frame& rhs) BOOST_NOEXCEPT { return rhs < lhs; }
+BOOST_CONSTEXPR inline bool operator<=(const frame& lhs, const frame& rhs) BOOST_NOEXCEPT { return !(lhs > rhs); }
+BOOST_CONSTEXPR inline bool operator>=(const frame& lhs, const frame& rhs) BOOST_NOEXCEPT { return !(lhs < rhs); }
+BOOST_CONSTEXPR inline bool operator==(const frame& lhs, const frame& rhs) BOOST_NOEXCEPT { return lhs.address() == rhs.address(); }
+BOOST_CONSTEXPR inline bool operator!=(const frame& lhs, const frame& rhs) BOOST_NOEXCEPT { return !(lhs == rhs); }
+
+/// Fast hashing support, O(1) complexity; Async-Handler-Safe.
+inline std::size_t hash_value(const frame& f) BOOST_NOEXCEPT {
+ return reinterpret_cast<std::size_t>(f.address());
+}
+
+/// Outputs stacktrace::frame in a human readable format to string; unsafe to use in async handlers.
+BOOST_STACKTRACE_FUNCTION std::string to_string(const frame& f);
+
+/// Outputs stacktrace::frame in a human readable format to output stream; unsafe to use in async handlers.
+template <class CharT, class TraitsT>
+std::basic_ostream<CharT, TraitsT>& operator<<(std::basic_ostream<CharT, TraitsT>& os, const frame& f) {
+ return os << boost::stacktrace::to_string(f);
+}
+
+}} // namespace boost::stacktrace
+
+/// @cond
+
+#include <boost/stacktrace/detail/pop_options.pp>
+
+#ifndef BOOST_STACKTRACE_LINK
+# if defined(BOOST_STACKTRACE_USE_NOOP)
+# include <boost/stacktrace/detail/frame_noop.ipp>
+# elif defined(BOOST_MSVC) || defined(BOOST_STACKTRACE_USE_WINDBG) || defined(BOOST_STACKTRACE_USE_WINDBG_CACHED)
+# include <boost/stacktrace/detail/frame_msvc.ipp>
+# else
+# include <boost/stacktrace/detail/frame_unwind.ipp>
+# endif
+#endif
+/// @endcond
+
+
+#endif // BOOST_STACKTRACE_FRAME_HPP
diff --git a/boost/stacktrace/safe_dump_to.hpp b/boost/stacktrace/safe_dump_to.hpp
new file mode 100644
index 0000000000..79981dabea
--- /dev/null
+++ b/boost/stacktrace/safe_dump_to.hpp
@@ -0,0 +1,218 @@
+// Copyright Antony Polukhin, 2016-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_STACKTRACE_SAFE_DUMP_TO_HPP
+#define BOOST_STACKTRACE_SAFE_DUMP_TO_HPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/stacktrace/detail/push_options.pp>
+
+#ifdef BOOST_INTEL
+# pragma warning(push)
+# pragma warning(disable:2196) // warning #2196: routine is both "inline" and "noinline"
+#endif
+
+/// @file safe_dump_to.hpp This header contains low-level async-signal-safe functions for dumping call stacks. Dumps are binary serialized arrays of `void*`,
+/// so you could read them by using 'od -tx8 -An stacktrace_dump_failename' Linux command or using boost::stacktrace::stacktrace::from_dump functions.
+
+namespace boost { namespace stacktrace {
+
+/// @cond
+namespace detail {
+
+ typedef const void* native_frame_ptr_t; // TODO: change to `typedef void(*native_frame_ptr_t)();`
+ enum helper{ max_frames_dump = 128 };
+
+ BOOST_STACKTRACE_FUNCTION std::size_t from_dump(const char* filename, native_frame_ptr_t* out_frames);
+ BOOST_STACKTRACE_FUNCTION std::size_t dump(const char* file, const native_frame_ptr_t* frames, std::size_t frames_count) BOOST_NOEXCEPT;
+#if defined(BOOST_WINDOWS)
+ BOOST_STACKTRACE_FUNCTION std::size_t dump(void* fd, const native_frame_ptr_t* frames, std::size_t frames_count) BOOST_NOEXCEPT;
+#else
+ // POSIX
+ BOOST_STACKTRACE_FUNCTION std::size_t dump(int fd, const native_frame_ptr_t* frames, std::size_t frames_count) BOOST_NOEXCEPT;
+#endif
+
+
+struct this_thread_frames { // struct is required to avoid warning about usage of inline+BOOST_NOINLINE
+ BOOST_NOINLINE BOOST_STACKTRACE_FUNCTION static std::size_t collect(native_frame_ptr_t* out_frames, std::size_t max_frames_count, std::size_t skip) BOOST_NOEXCEPT;
+
+ BOOST_NOINLINE static std::size_t safe_dump_to_impl(void* memory, std::size_t size, std::size_t skip) BOOST_NOEXCEPT {
+ typedef boost::stacktrace::detail::native_frame_ptr_t native_frame_ptr_t;
+
+ if (size < sizeof(native_frame_ptr_t)) {
+ return 0;
+ }
+
+ native_frame_ptr_t* mem = static_cast<native_frame_ptr_t*>(memory);
+ const std::size_t frames_count = boost::stacktrace::detail::this_thread_frames::collect(mem, size / sizeof(native_frame_ptr_t) - 1, skip + 1);
+ mem[frames_count] = 0;
+ return frames_count + 1;
+ }
+
+ template <class T>
+ BOOST_NOINLINE static std::size_t safe_dump_to_impl(T file, std::size_t skip, std::size_t max_depth) BOOST_NOEXCEPT {
+ typedef boost::stacktrace::detail::native_frame_ptr_t native_frame_ptr_t;
+
+ native_frame_ptr_t buffer[boost::stacktrace::detail::max_frames_dump + 1];
+ if (max_depth > boost::stacktrace::detail::max_frames_dump) {
+ max_depth = boost::stacktrace::detail::max_frames_dump;
+ }
+
+ const std::size_t frames_count = boost::stacktrace::detail::this_thread_frames::collect(buffer, max_depth, skip + 1);
+ buffer[frames_count] = 0;
+ return boost::stacktrace::detail::dump(file, buffer, frames_count + 1);
+ }
+};
+
+} // namespace detail
+/// @endcond
+
+/// @brief Stores current function call sequence into the memory.
+///
+/// @b Complexity: O(N) where N is call sequence length, O(1) if BOOST_STACKTRACE_USE_NOOP is defined.
+///
+/// @b Async-Handler-Safety: Safe.
+///
+/// @returns Stored call sequence depth including terminating zero frame.
+///
+/// @param memory Preallocated buffer to store current function call sequence into.
+///
+/// @param size Size of the preallocated buffer.
+BOOST_FORCEINLINE std::size_t safe_dump_to(void* memory, std::size_t size) BOOST_NOEXCEPT {
+ return boost::stacktrace::detail::this_thread_frames::safe_dump_to_impl(memory, size, 0);
+}
+
+/// @brief Stores current function call sequence into the memory.
+///
+/// @b Complexity: O(N) where N is call sequence length, O(1) if BOOST_STACKTRACE_USE_NOOP is defined.
+///
+/// @b Async-Handler-Safety: Safe.
+///
+/// @returns Stored call sequence depth including terminating zero frame.
+///
+/// @param skip How many top calls to skip and do not store.
+///
+/// @param memory Preallocated buffer to store current function call sequence into.
+///
+/// @param size Size of the preallocated buffer.
+BOOST_FORCEINLINE std::size_t safe_dump_to(std::size_t skip, void* memory, std::size_t size) BOOST_NOEXCEPT {
+ return boost::stacktrace::detail::this_thread_frames::safe_dump_to_impl(memory, size, skip);
+}
+
+
+/// @brief Opens a file and rewrites its content with current function call sequence.
+///
+/// @b Complexity: O(N) where N is call sequence length, O(1) if BOOST_STACKTRACE_USE_NOOP is defined.
+///
+/// @b Async-Handler-Safety: Safe.
+///
+/// @returns Stored call sequence depth including terminating zero frame.
+///
+/// @param file File to store current function call sequence.
+BOOST_FORCEINLINE std::size_t safe_dump_to(const char* file) BOOST_NOEXCEPT {
+ return boost::stacktrace::detail::this_thread_frames::safe_dump_to_impl(file, 0, boost::stacktrace::detail::max_frames_dump);
+}
+
+/// @brief Opens a file and rewrites its content with current function call sequence.
+///
+/// @b Complexity: O(N) where N is call sequence length, O(1) if BOOST_STACKTRACE_USE_NOOP is defined.
+///
+/// @b Async-Handler-Safety: Safe.
+///
+/// @returns Stored call sequence depth including terminating zero frame.
+///
+/// @param skip How many top calls to skip and do not store.
+///
+/// @param max_depth Max call sequence depth to collect.
+///
+/// @param file File to store current function call sequence.
+BOOST_FORCEINLINE std::size_t safe_dump_to(std::size_t skip, std::size_t max_depth, const char* file) BOOST_NOEXCEPT {
+ return boost::stacktrace::detail::this_thread_frames::safe_dump_to_impl(file, skip, max_depth);
+}
+
+#ifdef BOOST_STACKTRACE_DOXYGEN_INVOKED
+
+/// @brief Writes into the provided file descriptor the current function call sequence.
+///
+/// @b Complexity: O(N) where N is call sequence length, O(1) if BOOST_STACKTRACE_USE_NOOP is defined.
+///
+/// @b Async-Handler-Safety: Safe.
+///
+/// @returns Stored call sequence depth including terminating zero frame.
+///
+/// @param file File to store current function call sequence.
+BOOST_FORCEINLINE std::size_t safe_dump_to(platform_specific_descriptor fd) BOOST_NOEXCEPT;
+
+/// @brief Writes into the provided file descriptor the current function call sequence.
+///
+/// @b Complexity: O(N) where N is call sequence length, O(1) if BOOST_STACKTRACE_USE_NOOP is defined.
+///
+/// @b Async-Handler-Safety: Safe.
+///
+/// @returns Stored call sequence depth including terminating zero frame.
+///
+/// @param skip How many top calls to skip and do not store.
+///
+/// @param max_depth Max call sequence depth to collect.
+///
+/// @param file File to store current function call sequence.
+BOOST_FORCEINLINE std::size_t safe_dump_to(std::size_t skip, std::size_t max_depth, platform_specific_descriptor fd) BOOST_NOEXCEPT;
+
+#elif defined(BOOST_WINDOWS)
+
+BOOST_FORCEINLINE std::size_t safe_dump_to(void* fd) BOOST_NOEXCEPT {
+ return boost::stacktrace::detail::this_thread_frames::safe_dump_to_impl(fd, 0, boost::stacktrace::detail::max_frames_dump);
+}
+
+BOOST_FORCEINLINE std::size_t safe_dump_to(std::size_t skip, std::size_t max_depth, void* fd) BOOST_NOEXCEPT {
+ return boost::stacktrace::detail::this_thread_frames::safe_dump_to_impl(fd, skip, max_depth);
+}
+
+#else
+
+// POSIX
+BOOST_FORCEINLINE std::size_t safe_dump_to(int fd) BOOST_NOEXCEPT {
+ return boost::stacktrace::detail::this_thread_frames::safe_dump_to_impl(fd, 0, boost::stacktrace::detail::max_frames_dump);
+}
+
+BOOST_FORCEINLINE std::size_t safe_dump_to(std::size_t skip, std::size_t max_depth, int fd) BOOST_NOEXCEPT {
+ return boost::stacktrace::detail::this_thread_frames::safe_dump_to_impl(fd, skip, max_depth);
+}
+
+#endif
+
+
+}} // namespace boost::stacktrace
+
+#ifdef BOOST_INTEL
+# pragma warning(pop)
+#endif
+
+#include <boost/stacktrace/detail/pop_options.pp>
+
+#if !defined(BOOST_STACKTRACE_LINK) || defined(BOOST_STACKTRACE_INTERNAL_BUILD_LIBS)
+# if defined(BOOST_STACKTRACE_USE_NOOP)
+# include <boost/stacktrace/detail/safe_dump_noop.ipp>
+# include <boost/stacktrace/detail/collect_noop.ipp>
+# else
+# if defined(BOOST_WINDOWS)
+# include <boost/stacktrace/detail/safe_dump_win.ipp>
+# else
+# include <boost/stacktrace/detail/safe_dump_posix.ipp>
+# endif
+# if defined(BOOST_WINDOWS) && !defined(BOOST_GCC)
+# include <boost/stacktrace/detail/collect_msvc.ipp>
+# else
+# include <boost/stacktrace/detail/collect_unwind.ipp>
+# endif
+# endif
+#endif
+
+#endif // BOOST_STACKTRACE_SAFE_DUMP_TO_HPP
diff --git a/boost/stacktrace/stacktrace.hpp b/boost/stacktrace/stacktrace.hpp
new file mode 100644
index 0000000000..3c72488767
--- /dev/null
+++ b/boost/stacktrace/stacktrace.hpp
@@ -0,0 +1,414 @@
+// Copyright Antony Polukhin, 2016-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_STACKTRACE_STACKTRACE_HPP
+#define BOOST_STACKTRACE_STACKTRACE_HPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/core/explicit_operator_bool.hpp>
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+#ifndef BOOST_NO_CXX11_HDR_TYPE_TRAITS
+# include <type_traits>
+#endif
+
+#include <boost/stacktrace/stacktrace_fwd.hpp>
+#include <boost/stacktrace/safe_dump_to.hpp>
+#include <boost/stacktrace/detail/frame_decl.hpp>
+
+#ifdef BOOST_INTEL
+# pragma warning(push)
+# pragma warning(disable:2196) // warning #2196: routine is both "inline" and "noinline"
+#endif
+
+/// @cond
+namespace boost {
+ // Forward declaration
+ template <class It> std::size_t hash_range(It, It);
+}
+/// @endcond
+
+namespace boost { namespace stacktrace {
+
+/// Class that on construction copies minimal information about call stack into its internals and provides access to that information.
+/// @tparam Allocator Allocator to use during stack capture.
+template <class Allocator>
+class basic_stacktrace {
+ std::vector<boost::stacktrace::frame, Allocator> impl_;
+ typedef boost::stacktrace::detail::native_frame_ptr_t native_frame_ptr_t;
+
+ /// @cond
+ void fill(native_frame_ptr_t* begin, std::size_t size) {
+ if (!size) {
+ return;
+ }
+
+ impl_.reserve(static_cast<std::size_t>(size));
+ for (std::size_t i = 0; i < size; ++i) {
+ if (!begin[i]) {
+ return;
+ }
+ impl_.push_back(
+ frame(begin[i])
+ );
+ }
+ }
+
+ static std::size_t frames_count_from_buffer_size(std::size_t buffer_size) BOOST_NOEXCEPT {
+ const std::size_t ret = (buffer_size > sizeof(native_frame_ptr_t) ? buffer_size / sizeof(native_frame_ptr_t) : 0);
+ return (ret > 1024 ? 1024 : ret); // Dealing with suspiciously big sizes
+ }
+
+ BOOST_NOINLINE void init(std::size_t frames_to_skip, std::size_t max_depth) {
+ BOOST_CONSTEXPR_OR_CONST std::size_t buffer_size = 128;
+ if (!max_depth) {
+ return;
+ }
+
+ try {
+ { // Fast path without additional allocations
+ native_frame_ptr_t buffer[buffer_size];
+ const std::size_t frames_count = boost::stacktrace::detail::this_thread_frames::collect(buffer, buffer_size, frames_to_skip + 1);
+ if (buffer_size > frames_count || frames_count >= max_depth) {
+ const std::size_t size = (max_depth < frames_count ? max_depth : frames_count);
+ fill(buffer, size);
+ return;
+ }
+ }
+
+ // Failed to fit in `buffer_size`. Allocating memory:
+ typedef typename Allocator::template rebind<native_frame_ptr_t>::other allocator_void_t;
+ std::vector<native_frame_ptr_t, allocator_void_t> buf(buffer_size * 2, 0, impl_.get_allocator());
+ do {
+ const std::size_t frames_count = boost::stacktrace::detail::this_thread_frames::collect(&buf[0], buf.size(), frames_to_skip + 1);
+ if (buf.size() > frames_count || frames_count >= max_depth) {
+ const std::size_t size = (max_depth < frames_count ? max_depth : frames_count);
+ fill(&buf[0], size);
+ return;
+ }
+
+ buf.resize(buf.size() * 2);
+ } while (buf.size() < buf.max_size()); // close to `true`, but suppresses `C4127: conditional expression is constant`.
+ } catch (...) {
+ // ignore exception
+ }
+ }
+ /// @endcond
+
+public:
+ typedef typename std::vector<boost::stacktrace::frame, Allocator>::value_type value_type;
+ typedef typename std::vector<boost::stacktrace::frame, Allocator>::allocator_type allocator_type;
+ typedef typename std::vector<boost::stacktrace::frame, Allocator>::const_pointer pointer;
+ typedef typename std::vector<boost::stacktrace::frame, Allocator>::const_pointer const_pointer;
+ typedef typename std::vector<boost::stacktrace::frame, Allocator>::const_reference reference;
+ typedef typename std::vector<boost::stacktrace::frame, Allocator>::const_reference const_reference;
+ typedef typename std::vector<boost::stacktrace::frame, Allocator>::size_type size_type;
+ typedef typename std::vector<boost::stacktrace::frame, Allocator>::difference_type difference_type;
+ typedef typename std::vector<boost::stacktrace::frame, Allocator>::const_iterator iterator;
+ typedef typename std::vector<boost::stacktrace::frame, Allocator>::const_iterator const_iterator;
+ typedef typename std::vector<boost::stacktrace::frame, Allocator>::const_reverse_iterator reverse_iterator;
+ typedef typename std::vector<boost::stacktrace::frame, Allocator>::const_reverse_iterator const_reverse_iterator;
+
+ /// @brief Stores the current function call sequence inside *this without any decoding or any other heavy platform specific operations.
+ ///
+ /// @b Complexity: O(N) where N is call sequence length, O(1) if BOOST_STACKTRACE_USE_NOOP is defined.
+ ///
+ /// @b Async-Handler-Safety: Safe if Allocator construction, copying, Allocator::allocate and Allocator::deallocate are async signal safe.
+ BOOST_FORCEINLINE basic_stacktrace() BOOST_NOEXCEPT
+ : impl_()
+ {
+ init(0 , static_cast<std::size_t>(-1));
+ }
+
+ /// @brief Stores the current function call sequence inside *this without any decoding or any other heavy platform specific operations.
+ ///
+ /// @b Complexity: O(N) where N is call sequence length, O(1) if BOOST_STACKTRACE_USE_NOOP is defined.
+ ///
+ /// @b Async-Handler-Safety: Safe if Allocator construction, copying, Allocator::allocate and Allocator::deallocate are async signal safe.
+ ///
+ /// @param a Allocator that would be passed to underlying storeage.
+ BOOST_FORCEINLINE explicit basic_stacktrace(const allocator_type& a) BOOST_NOEXCEPT
+ : impl_(a)
+ {
+ init(0 , static_cast<std::size_t>(-1));
+ }
+
+ /// @brief Stores [skip, skip + max_depth) of the current function call sequence inside *this without any decoding or any other heavy platform specific operations.
+ ///
+ /// @b Complexity: O(N) where N is call sequence length, O(1) if BOOST_STACKTRACE_USE_NOOP is defined.
+ ///
+ /// @b Async-Handler-Safety: Safe if Allocator construction, copying, Allocator::allocate and Allocator::deallocate are async signal safe.
+ ///
+ /// @param skip How many top calls to skip and do not store in *this.
+ ///
+ /// @param max_depth Max call sequence depth to collect.
+ ///
+ /// @param a Allocator that would be passed to underlying storeage.
+ ///
+ /// @throws Nothing. Note that default construction of allocator may throw, however it is
+ /// performed outside the constructor and exception in `allocator_type()` would not result in calling `std::terminate`.
+ BOOST_FORCEINLINE basic_stacktrace(std::size_t skip, std::size_t max_depth, const allocator_type& a = allocator_type()) BOOST_NOEXCEPT
+ : impl_(a)
+ {
+ init(skip , max_depth);
+ }
+
+ /// @b Complexity: O(st.size())
+ ///
+ /// @b Async-Handler-Safety: Safe if Allocator construction, copying, Allocator::allocate and Allocator::deallocate are async signal safe.
+ basic_stacktrace(const basic_stacktrace& st)
+ : impl_(st.impl_)
+ {}
+
+ /// @b Complexity: O(st.size())
+ ///
+ /// @b Async-Handler-Safety: Safe if Allocator construction, copying, Allocator::allocate and Allocator::deallocate are async signal safe.
+ basic_stacktrace& operator=(const basic_stacktrace& st) {
+ impl_ = st.impl_;
+ return *this;
+ }
+
+#ifdef BOOST_STACKTRACE_DOXYGEN_INVOKED
+ /// @b Complexity: O(1)
+ ///
+ /// @b Async-Handler-Safety: Safe if Allocator::deallocate is async signal safe.
+ ~basic_stacktrace() BOOST_NOEXCEPT = default;
+#endif
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ /// @b Complexity: O(1)
+ ///
+ /// @b Async-Handler-Safety: Safe if Allocator construction and copying are async signal safe.
+ basic_stacktrace(basic_stacktrace&& st) BOOST_NOEXCEPT
+ : impl_(std::move(st.impl_))
+ {}
+
+ /// @b Complexity: O(st.size())
+ ///
+ /// @b Async-Handler-Safety: Safe if Allocator construction and copying are async signal safe.
+ basic_stacktrace& operator=(basic_stacktrace&& st)
+#ifndef BOOST_NO_CXX11_HDR_TYPE_TRAITS
+ BOOST_NOEXCEPT_IF(( std::is_nothrow_move_assignable< std::vector<boost::stacktrace::frame, Allocator> >::value ))
+#else
+ BOOST_NOEXCEPT
+#endif
+ {
+ impl_ = std::move(st.impl_);
+ return *this;
+ }
+#endif
+
+ /// @returns Number of function names stored inside the class.
+ ///
+ /// @b Complexity: O(1)
+ ///
+ /// @b Async-Handler-Safety: Safe.
+ size_type size() const BOOST_NOEXCEPT {
+ return impl_.size();
+ }
+
+ /// @param frame_no Zero based index of frame to return. 0
+ /// is the function index where stacktrace was constructed and
+ /// index close to this->size() contains function `main()`.
+ /// @returns frame that references the actual frame info, stored inside *this.
+ ///
+ /// @b Complexity: O(1).
+ ///
+ /// @b Async-Handler-Safety: Safe.
+ const_reference operator[](std::size_t frame_no) const BOOST_NOEXCEPT {
+ return impl_[frame_no];
+ }
+
+ /// @b Complexity: O(1)
+ ///
+ /// @b Async-Handler-Safety: Safe.
+ const_iterator begin() const BOOST_NOEXCEPT { return impl_.begin(); }
+ /// @b Complexity: O(1)
+ ///
+ /// @b Async-Handler-Safety: Safe.
+ const_iterator cbegin() const BOOST_NOEXCEPT { return impl_.begin(); }
+ /// @b Complexity: O(1)
+ ///
+ /// @b Async-Handler-Safety: Safe.
+ const_iterator end() const BOOST_NOEXCEPT { return impl_.end(); }
+ /// @b Complexity: O(1)
+ ///
+ /// @b Async-Handler-Safety: Safe.
+ const_iterator cend() const BOOST_NOEXCEPT { return impl_.end(); }
+
+ /// @b Complexity: O(1)
+ ///
+ /// @b Async-Handler-Safety: Safe.
+ const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return impl_.rbegin(); }
+ /// @b Complexity: O(1)
+ ///
+ /// @b Async-Handler-Safety: Safe.
+ const_reverse_iterator crbegin() const BOOST_NOEXCEPT { return impl_.rbegin(); }
+ /// @b Complexity: O(1)
+ ///
+ /// @b Async-Handler-Safety: Safe.
+ const_reverse_iterator rend() const BOOST_NOEXCEPT { return impl_.rend(); }
+ /// @b Complexity: O(1)
+ ///
+ /// @b Async-Handler-Safety: Safe.
+ const_reverse_iterator crend() const BOOST_NOEXCEPT { return impl_.rend(); }
+
+
+ /// @brief Allows to check that stack trace capturing was successful.
+ /// @returns `true` if `this->size() != 0`
+ ///
+ /// @b Complexity: O(1)
+ ///
+ /// @b Async-Handler-Safety: Safe.
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+
+ /// @brief Allows to check that stack trace failed.
+ /// @returns `true` if `this->size() == 0`
+ ///
+ /// @b Complexity: O(1)
+ ///
+ /// @b Async-Handler-Safety: Safe.
+ bool empty() const BOOST_NOEXCEPT { return !size(); }
+
+ /// @cond
+ bool operator!() const BOOST_NOEXCEPT { return !size(); }
+ /// @endcond
+
+ const std::vector<boost::stacktrace::frame, Allocator>& as_vector() const BOOST_NOEXCEPT {
+ return impl_;
+ }
+
+ /// Constructs stacktrace from basic_istreamable that references the dumped stacktrace. Terminating zero frame is discarded.
+ ///
+ /// @b Complexity: O(N)
+ template <class Char, class Trait>
+ static basic_stacktrace from_dump(std::basic_istream<Char, Trait>& in, const allocator_type& a = allocator_type()) {
+ typedef typename std::basic_istream<Char, Trait>::pos_type pos_type;
+ basic_stacktrace ret(0, 0, a);
+
+ // reserving space
+ const pos_type pos = in.tellg();
+ in.seekg(0, in.end);
+ const std::size_t frames_count = frames_count_from_buffer_size(static_cast<std::size_t>(in.tellg()));
+ in.seekg(pos);
+
+ if (!frames_count) {
+ return ret;
+ }
+
+ native_frame_ptr_t ptr = 0;
+ ret.impl_.reserve(frames_count);
+ while (in.read(reinterpret_cast<Char*>(&ptr), sizeof(ptr))) {
+ if (!ptr) {
+ break;
+ }
+
+ ret.impl_.push_back(frame(ptr));
+ }
+
+ return ret;
+ }
+
+ /// Constructs stacktrace from raw memory dump. Terminating zero frame is discarded.
+ ///
+ /// @b Complexity: O(size) in worst case
+ static basic_stacktrace from_dump(const void* begin, std::size_t buffer_size_in_bytes, const allocator_type& a = allocator_type()) {
+ basic_stacktrace ret(0, 0, a);
+ const native_frame_ptr_t* first = static_cast<const native_frame_ptr_t*>(begin);
+ const std::size_t frames_count = frames_count_from_buffer_size(buffer_size_in_bytes);
+ if (!frames_count) {
+ return ret;
+ }
+
+ const native_frame_ptr_t* const last = first + frames_count;
+ ret.impl_.reserve(frames_count);
+ for (; first != last; ++first) {
+ if (!*first) {
+ break;
+ }
+
+ ret.impl_.push_back(frame(*first));
+ }
+
+ return ret;
+ }
+};
+
+/// @brief Compares stacktraces for less, order is platform dependent.
+///
+/// @b Complexity: Amortized O(1); worst case O(size())
+///
+/// @b Async-Handler-Safety: Safe.
+template <class Allocator1, class Allocator2>
+bool operator< (const basic_stacktrace<Allocator1>& lhs, const basic_stacktrace<Allocator2>& rhs) BOOST_NOEXCEPT {
+ return lhs.size() < rhs.size() || (lhs.size() == rhs.size() && lhs.as_vector() < rhs.as_vector());
+}
+
+/// @brief Compares stacktraces for equality.
+///
+/// @b Complexity: Amortized O(1); worst case O(size())
+///
+/// @b Async-Handler-Safety: Safe.
+template <class Allocator1, class Allocator2>
+bool operator==(const basic_stacktrace<Allocator1>& lhs, const basic_stacktrace<Allocator2>& rhs) BOOST_NOEXCEPT {
+ return lhs.as_vector() == rhs.as_vector();
+}
+
+
+/// Comparison operators that provide platform dependant ordering and have amortized O(1) complexity; O(size()) worst case complexity; are Async-Handler-Safe.
+template <class Allocator1, class Allocator2>
+bool operator> (const basic_stacktrace<Allocator1>& lhs, const basic_stacktrace<Allocator2>& rhs) BOOST_NOEXCEPT {
+ return rhs < lhs;
+}
+
+template <class Allocator1, class Allocator2>
+bool operator<=(const basic_stacktrace<Allocator1>& lhs, const basic_stacktrace<Allocator2>& rhs) BOOST_NOEXCEPT {
+ return !(lhs > rhs);
+}
+
+template <class Allocator1, class Allocator2>
+bool operator>=(const basic_stacktrace<Allocator1>& lhs, const basic_stacktrace<Allocator2>& rhs) BOOST_NOEXCEPT {
+ return !(lhs < rhs);
+}
+
+template <class Allocator1, class Allocator2>
+bool operator!=(const basic_stacktrace<Allocator1>& lhs, const basic_stacktrace<Allocator2>& rhs) BOOST_NOEXCEPT {
+ return !(lhs == rhs);
+}
+
+/// Fast hashing support, O(st.size()) complexity; Async-Handler-Safe.
+template <class Allocator>
+std::size_t hash_value(const basic_stacktrace<Allocator>& st) BOOST_NOEXCEPT {
+ return boost::hash_range(st.as_vector().begin(), st.as_vector().end());
+}
+
+/// Outputs stacktrace in a human readable format to output stream; unsafe to use in async handlers.
+template <class CharT, class TraitsT, class Allocator>
+std::basic_ostream<CharT, TraitsT>& operator<<(std::basic_ostream<CharT, TraitsT>& os, const basic_stacktrace<Allocator>& bt) {
+ if (bt) {
+ os << boost::stacktrace::detail::to_string(&bt.as_vector()[0], bt.size());
+ }
+
+ return os;
+}
+
+/// This is the typedef to use unless you'd like to provide a specific allocator to boost::stacktrace::basic_stacktrace.
+typedef basic_stacktrace<> stacktrace;
+
+}} // namespace boost::stacktrace
+
+#ifdef BOOST_INTEL
+# pragma warning(pop)
+#endif
+
+#endif // BOOST_STACKTRACE_STACKTRACE_HPP
diff --git a/boost/stacktrace/stacktrace_fwd.hpp b/boost/stacktrace/stacktrace_fwd.hpp
new file mode 100644
index 0000000000..ec131564c0
--- /dev/null
+++ b/boost/stacktrace/stacktrace_fwd.hpp
@@ -0,0 +1,28 @@
+// Copyright Antony Polukhin, 2016-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_STACKTRACE_STACKTRACE_FWD_HPP
+#define BOOST_STACKTRACE_STACKTRACE_FWD_HPP
+
+#include <cstddef>
+#include <memory>
+
+/// @file stacktrace_fwd.hpp This header contains only forward declarations of
+/// boost::stacktrace::frame, boost::stacktrace::basic_stacktrace, boost::stacktrace::stacktrace
+/// and does not include any other Boost headers.
+
+/// @cond
+namespace boost { namespace stacktrace {
+
+class frame;
+template <class Allocator = std::allocator<frame> > class basic_stacktrace;
+typedef basic_stacktrace<> stacktrace;
+
+}} // namespace boost::stacktrace
+/// @endcond
+
+
+#endif // BOOST_STACKTRACE_STACKTRACE_FWD_HPP
diff --git a/boost/system/detail/error_code.ipp b/boost/system/detail/error_code.ipp
index 71c60f61da..51ba3f4747 100644
--- a/boost/system/detail/error_code.ipp
+++ b/boost/system/detail/error_code.ipp
@@ -1,4 +1,4 @@
-// error_code support implementation file ----------------------------------//
+// error_code support implementation file --------------------------------------------//
// Copyright Beman Dawes 2002, 2006
// Copyright (c) Microsoft Corporation 2014
@@ -7,7 +7,7 @@
// See library home page at http://www.boost.org/libs/system
-//----------------------------------------------------------------------------//
+//--------------------------------------------------------------------------------------//
#include <boost/config/warning_disable.hpp>
@@ -21,7 +21,9 @@
#include <cstring> // for strerror/strerror_r
# if defined( BOOST_WINDOWS_API )
-# include <windows.h>
+# include <boost/detail/winapi/error_codes.hpp>
+# include <boost/detail/winapi/error_handling.hpp>
+# include <boost/detail/winapi/character_code_conversion.hpp>
# if !BOOST_PLAT_WINDOWS_RUNTIME
# include <boost/system/detail/local_free_on_destruction.hpp>
# endif
@@ -30,7 +32,7 @@
# endif
# endif
-//----------------------------------------------------------------------------//
+//--------------------------------------------------------------------------------------//
namespace boost
{
namespace system
@@ -39,7 +41,7 @@ namespace boost
namespace
{
- // standard error categories ---------------------------------------------//
+ // standard error categories -------------------------------------------------------//
class generic_error_category : public error_category
{
@@ -84,7 +86,8 @@ namespace
// -- VMS doesn't provide strerror_r, but on this platform, strerror is
// thread safe.
# if defined(BOOST_WINDOWS_API) || defined(__hpux) || defined(__sun)\
- || (defined(__linux) && (!defined(__USE_XOPEN2K) || defined(BOOST_SYSTEM_USE_STRERROR)))\
+ || (defined(__linux) && (!defined(__USE_XOPEN2K)\
+ || defined(BOOST_SYSTEM_USE_STRERROR)))\
|| (defined(__osf__) && !defined(_REENTRANT))\
|| (defined(__INTEGRITY))\
|| (defined(__vms))\
@@ -156,14 +159,15 @@ namespace
# endif // else POSIX version of strerror_r
# endif // else use strerror_r
}
- // system_error_category implementation --------------------------------//
+ // system_error_category implementation --------------------------------------------//
const char * system_error_category::name() const BOOST_SYSTEM_NOEXCEPT
{
return "system";
}
- error_condition system_error_category::default_error_condition( int ev ) const BOOST_SYSTEM_NOEXCEPT
+ error_condition system_error_category::default_error_condition( int ev ) const
+ BOOST_SYSTEM_NOEXCEPT
{
using namespace boost::system::errc;
#if defined(__PGI)
@@ -181,11 +185,17 @@ namespace
# endif
# endif
+# if defined(BOOST_WINDOWS_API)
+
+ using namespace boost::detail::winapi; // for error codes
+
+# endif
+
switch ( ev )
{
case 0: return make_error_condition( success );
# if defined(BOOST_POSIX_API)
- // POSIX-like O/S -> posix_errno decode table ---------------------------//
+ // POSIX-like O/S -> posix_errno decode table -------------------------------------//
case E2BIG: return make_error_condition( argument_list_too_long );
case EACCES: return make_error_condition( permission_denied );
case EADDRINUSE: return make_error_condition( address_in_use );
@@ -279,80 +289,81 @@ namespace
#else
// Windows system -> posix_errno decode table ---------------------------//
// see WinError.h comments for descriptions of errors
- case ERROR_ACCESS_DENIED: return make_error_condition( permission_denied );
- case ERROR_ALREADY_EXISTS: return make_error_condition( file_exists );
- case ERROR_BAD_UNIT: return make_error_condition( no_such_device );
- case ERROR_BUFFER_OVERFLOW: return make_error_condition( filename_too_long );
- case ERROR_BUSY: return make_error_condition( device_or_resource_busy );
- case ERROR_BUSY_DRIVE: return make_error_condition( device_or_resource_busy );
- case ERROR_CANNOT_MAKE: return make_error_condition( permission_denied );
- case ERROR_CANTOPEN: return make_error_condition( io_error );
- case ERROR_CANTREAD: return make_error_condition( io_error );
- case ERROR_CANTWRITE: return make_error_condition( io_error );
- case ERROR_CURRENT_DIRECTORY: return make_error_condition( permission_denied );
- case ERROR_DEV_NOT_EXIST: return make_error_condition( no_such_device );
- case ERROR_DEVICE_IN_USE: return make_error_condition( device_or_resource_busy );
- case ERROR_DIR_NOT_EMPTY: return make_error_condition( directory_not_empty );
- case ERROR_DIRECTORY: return make_error_condition( invalid_argument ); // WinError.h: "The directory name is invalid"
- case ERROR_DISK_FULL: return make_error_condition( no_space_on_device );
- case ERROR_FILE_EXISTS: return make_error_condition( file_exists );
- case ERROR_FILE_NOT_FOUND: return make_error_condition( no_such_file_or_directory );
- case ERROR_HANDLE_DISK_FULL: return make_error_condition( no_space_on_device );
- case ERROR_INVALID_ACCESS: return make_error_condition( permission_denied );
- case ERROR_INVALID_DRIVE: return make_error_condition( no_such_device );
- case ERROR_INVALID_FUNCTION: return make_error_condition( function_not_supported );
- case ERROR_INVALID_HANDLE: return make_error_condition( invalid_argument );
- case ERROR_INVALID_NAME: return make_error_condition( invalid_argument );
- case ERROR_LOCK_VIOLATION: return make_error_condition( no_lock_available );
- case ERROR_LOCKED: return make_error_condition( no_lock_available );
- case ERROR_NEGATIVE_SEEK: return make_error_condition( invalid_argument );
- case ERROR_NOACCESS: return make_error_condition( permission_denied );
- case ERROR_NOT_ENOUGH_MEMORY: return make_error_condition( not_enough_memory );
- case ERROR_NOT_READY: return make_error_condition( resource_unavailable_try_again );
- case ERROR_NOT_SAME_DEVICE: return make_error_condition( cross_device_link );
- case ERROR_OPEN_FAILED: return make_error_condition( io_error );
- case ERROR_OPEN_FILES: return make_error_condition( device_or_resource_busy );
- case ERROR_OPERATION_ABORTED: return make_error_condition( operation_canceled );
- case ERROR_OUTOFMEMORY: return make_error_condition( not_enough_memory );
- case ERROR_PATH_NOT_FOUND: return make_error_condition( no_such_file_or_directory );
- case ERROR_READ_FAULT: return make_error_condition( io_error );
- case ERROR_RETRY: return make_error_condition( resource_unavailable_try_again );
- case ERROR_SEEK: return make_error_condition( io_error );
- case ERROR_SHARING_VIOLATION: return make_error_condition( permission_denied );
- case ERROR_TOO_MANY_OPEN_FILES: return make_error_condition( too_many_files_open );
- case ERROR_WRITE_FAULT: return make_error_condition( io_error );
- case ERROR_WRITE_PROTECT: return make_error_condition( permission_denied );
- case WSAEACCES: return make_error_condition( permission_denied );
- case WSAEADDRINUSE: return make_error_condition( address_in_use );
- case WSAEADDRNOTAVAIL: return make_error_condition( address_not_available );
- case WSAEAFNOSUPPORT: return make_error_condition( address_family_not_supported );
- case WSAEALREADY: return make_error_condition( connection_already_in_progress );
- case WSAEBADF: return make_error_condition( bad_file_descriptor );
- case WSAECONNABORTED: return make_error_condition( connection_aborted );
- case WSAECONNREFUSED: return make_error_condition( connection_refused );
- case WSAECONNRESET: return make_error_condition( connection_reset );
- case WSAEDESTADDRREQ: return make_error_condition( destination_address_required );
- case WSAEFAULT: return make_error_condition( bad_address );
- case WSAEHOSTUNREACH: return make_error_condition( host_unreachable );
- case WSAEINPROGRESS: return make_error_condition( operation_in_progress );
- case WSAEINTR: return make_error_condition( interrupted );
- case WSAEINVAL: return make_error_condition( invalid_argument );
- case WSAEISCONN: return make_error_condition( already_connected );
- case WSAEMFILE: return make_error_condition( too_many_files_open );
- case WSAEMSGSIZE: return make_error_condition( message_size );
- case WSAENAMETOOLONG: return make_error_condition( filename_too_long );
- case WSAENETDOWN: return make_error_condition( network_down );
- case WSAENETRESET: return make_error_condition( network_reset );
- case WSAENETUNREACH: return make_error_condition( network_unreachable );
- case WSAENOBUFS: return make_error_condition( no_buffer_space );
- case WSAENOPROTOOPT: return make_error_condition( no_protocol_option );
- case WSAENOTCONN: return make_error_condition( not_connected );
- case WSAENOTSOCK: return make_error_condition( not_a_socket );
- case WSAEOPNOTSUPP: return make_error_condition( operation_not_supported );
- case WSAEPROTONOSUPPORT: return make_error_condition( protocol_not_supported );
- case WSAEPROTOTYPE: return make_error_condition( wrong_protocol_type );
- case WSAETIMEDOUT: return make_error_condition( timed_out );
- case WSAEWOULDBLOCK: return make_error_condition( operation_would_block );
+ case ERROR_ACCESS_DENIED_: return make_error_condition( permission_denied );
+ case ERROR_ALREADY_EXISTS_: return make_error_condition( file_exists );
+ case ERROR_BAD_UNIT_: return make_error_condition( no_such_device );
+ case ERROR_BUFFER_OVERFLOW_: return make_error_condition( filename_too_long );
+ case ERROR_BUSY_: return make_error_condition( device_or_resource_busy );
+ case ERROR_BUSY_DRIVE_: return make_error_condition( device_or_resource_busy );
+ case ERROR_CANNOT_MAKE_: return make_error_condition( permission_denied );
+ case ERROR_CANTOPEN_: return make_error_condition( io_error );
+ case ERROR_CANTREAD_: return make_error_condition( io_error );
+ case ERROR_CANTWRITE_: return make_error_condition( io_error );
+ case ERROR_CURRENT_DIRECTORY_: return make_error_condition( permission_denied );
+ case ERROR_DEV_NOT_EXIST_: return make_error_condition( no_such_device );
+ case ERROR_DEVICE_IN_USE_: return make_error_condition( device_or_resource_busy );
+ case ERROR_DIR_NOT_EMPTY_: return make_error_condition( directory_not_empty );
+ case ERROR_DIRECTORY_: return make_error_condition( invalid_argument );\
+ // WinError.h: "The directory name is invalid"
+ case ERROR_DISK_FULL_: return make_error_condition( no_space_on_device );
+ case ERROR_FILE_EXISTS_: return make_error_condition( file_exists );
+ case ERROR_FILE_NOT_FOUND_: return make_error_condition( no_such_file_or_directory );
+ case ERROR_HANDLE_DISK_FULL_: return make_error_condition( no_space_on_device );
+ case ERROR_INVALID_ACCESS_: return make_error_condition( permission_denied );
+ case ERROR_INVALID_DRIVE_: return make_error_condition( no_such_device );
+ case ERROR_INVALID_FUNCTION_: return make_error_condition( function_not_supported );
+ case ERROR_INVALID_HANDLE_: return make_error_condition( invalid_argument );
+ case ERROR_INVALID_NAME_: return make_error_condition( invalid_argument );
+ case ERROR_LOCK_VIOLATION_: return make_error_condition( no_lock_available );
+ case ERROR_LOCKED_: return make_error_condition( no_lock_available );
+ case ERROR_NEGATIVE_SEEK_: return make_error_condition( invalid_argument );
+ case ERROR_NOACCESS_: return make_error_condition( permission_denied );
+ case ERROR_NOT_ENOUGH_MEMORY_: return make_error_condition( not_enough_memory );
+ case ERROR_NOT_READY_: return make_error_condition( resource_unavailable_try_again );
+ case ERROR_NOT_SAME_DEVICE_: return make_error_condition( cross_device_link );
+ case ERROR_OPEN_FAILED_: return make_error_condition( io_error );
+ case ERROR_OPEN_FILES_: return make_error_condition( device_or_resource_busy );
+ case ERROR_OPERATION_ABORTED_: return make_error_condition( operation_canceled );
+ case ERROR_OUTOFMEMORY_: return make_error_condition( not_enough_memory );
+ case ERROR_PATH_NOT_FOUND_: return make_error_condition( no_such_file_or_directory );
+ case ERROR_READ_FAULT_: return make_error_condition( io_error );
+ case ERROR_RETRY_: return make_error_condition( resource_unavailable_try_again );
+ case ERROR_SEEK_: return make_error_condition( io_error );
+ case ERROR_SHARING_VIOLATION_: return make_error_condition( permission_denied );
+ case ERROR_TOO_MANY_OPEN_FILES_: return make_error_condition( too_many_files_open );
+ case ERROR_WRITE_FAULT_: return make_error_condition( io_error );
+ case ERROR_WRITE_PROTECT_: return make_error_condition( permission_denied );
+ case WSAEACCES_: return make_error_condition( permission_denied );
+ case WSAEADDRINUSE_: return make_error_condition( address_in_use );
+ case WSAEADDRNOTAVAIL_: return make_error_condition( address_not_available );
+ case WSAEAFNOSUPPORT_: return make_error_condition( address_family_not_supported );
+ case WSAEALREADY_: return make_error_condition( connection_already_in_progress );
+ case WSAEBADF_: return make_error_condition( bad_file_descriptor );
+ case WSAECONNABORTED_: return make_error_condition( connection_aborted );
+ case WSAECONNREFUSED_: return make_error_condition( connection_refused );
+ case WSAECONNRESET_: return make_error_condition( connection_reset );
+ case WSAEDESTADDRREQ_: return make_error_condition( destination_address_required );
+ case WSAEFAULT_: return make_error_condition( bad_address );
+ case WSAEHOSTUNREACH_: return make_error_condition( host_unreachable );
+ case WSAEINPROGRESS_: return make_error_condition( operation_in_progress );
+ case WSAEINTR_: return make_error_condition( interrupted );
+ case WSAEINVAL_: return make_error_condition( invalid_argument );
+ case WSAEISCONN_: return make_error_condition( already_connected );
+ case WSAEMFILE_: return make_error_condition( too_many_files_open );
+ case WSAEMSGSIZE_: return make_error_condition( message_size );
+ case WSAENAMETOOLONG_: return make_error_condition( filename_too_long );
+ case WSAENETDOWN_: return make_error_condition( network_down );
+ case WSAENETRESET_: return make_error_condition( network_reset );
+ case WSAENETUNREACH_: return make_error_condition( network_unreachable );
+ case WSAENOBUFS_: return make_error_condition( no_buffer_space );
+ case WSAENOPROTOOPT_: return make_error_condition( no_protocol_option );
+ case WSAENOTCONN_: return make_error_condition( not_connected );
+ case WSAENOTSOCK_: return make_error_condition( not_a_socket );
+ case WSAEOPNOTSUPP_: return make_error_condition( operation_not_supported );
+ case WSAEPROTONOSUPPORT_: return make_error_condition( protocol_not_supported );
+ case WSAEPROTOTYPE_: return make_error_condition( wrong_protocol_type );
+ case WSAETIMEDOUT_: return make_error_condition( timed_out );
+ case WSAEWOULDBLOCK_: return make_error_condition( operation_would_block );
#endif
default: return error_condition( ev, system_category() );
}
@@ -372,12 +383,13 @@ namespace
std::wstring buf(128, wchar_t());
for (;;)
{
- DWORD retval = ::FormatMessageW(
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
+ boost::detail::winapi::DWORD_ retval = boost::detail::winapi::FormatMessageW(
+ boost::detail::winapi::FORMAT_MESSAGE_FROM_SYSTEM_ |
+ boost::detail::winapi::FORMAT_MESSAGE_IGNORE_INSERTS_,
NULL,
ev,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ boost::detail::winapi::MAKELANGID_(boost::detail::winapi::LANG_NEUTRAL_,
+ boost::detail::winapi::SUBLANG_DEFAULT_), // Default language
&buf[0],
buf.size(),
NULL
@@ -388,7 +400,8 @@ namespace
buf.resize(retval);
break;
}
- else if ( ::GetLastError() != ERROR_INSUFFICIENT_BUFFER )
+ else if (boost::detail::winapi::GetLastError() !=
+ boost::detail::winapi::ERROR_INSUFFICIENT_BUFFER_)
{
return std::string("Unknown error");
}
@@ -399,23 +412,26 @@ namespace
}
int num_chars = (buf.size() + 1) * 2;
- LPSTR narrow_buffer = (LPSTR)_alloca( num_chars );
- if (::WideCharToMultiByte(CP_ACP, 0, buf.c_str(), -1, narrow_buffer, num_chars, NULL, NULL) == 0)
+ boost::detail::winapi::LPSTR_ narrow_buffer =
+ (boost::detail::winapi::LPSTR_)_alloca(num_chars);
+ if (boost::detail::winapi::WideCharToMultiByte(boost::detail::winapi::CP_ACP_, 0,
+ buf.c_str(), -1, narrow_buffer, num_chars, NULL, NULL) == 0)
{
return std::string("Unknown error");
}
std::string str( narrow_buffer );
#else
- LPVOID lpMsgBuf = 0;
- DWORD retval = ::FormatMessageA(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
+ boost::detail::winapi::LPVOID_ lpMsgBuf = 0;
+ boost::detail::winapi::DWORD_ retval = boost::detail::winapi::FormatMessageA(
+ boost::detail::winapi::FORMAT_MESSAGE_ALLOCATE_BUFFER_ |
+ boost::detail::winapi::FORMAT_MESSAGE_FROM_SYSTEM_ |
+ boost::detail::winapi::FORMAT_MESSAGE_IGNORE_INSERTS_,
NULL,
ev,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
- (LPSTR) &lpMsgBuf,
+ boost::detail::winapi::MAKELANGID_(boost::detail::winapi::LANG_NEUTRAL_,
+ boost::detail::winapi::SUBLANG_DEFAULT_), // Default language
+ (boost::detail::winapi::LPSTR_) &lpMsgBuf,
0,
NULL
);
@@ -423,7 +439,7 @@ namespace
if (retval == 0)
return std::string("Unknown error");
- std::string str( static_cast<LPCSTR>(lpMsgBuf) );
+ std::string str(static_cast<boost::detail::winapi::LPCSTR_>(lpMsgBuf));
# endif
while ( str.size()
&& (str[str.size()-1] == '\n' || str[str.size()-1] == '\r') )
diff --git a/boost/system/detail/local_free_on_destruction.hpp b/boost/system/detail/local_free_on_destruction.hpp
index 110024f3d5..25f879b3b0 100644
--- a/boost/system/detail/local_free_on_destruction.hpp
+++ b/boost/system/detail/local_free_on_destruction.hpp
@@ -12,6 +12,8 @@
#ifndef BOOST_SYSTEM_LOCAL_FREE_ON_EXIT_HPP
#define BOOST_SYSTEM_LOCAL_FREE_ON_EXIT_HPP
+#include <boost/detail/winapi/local_memory.hpp>
+
namespace boost {
namespace system {
namespace detail {
@@ -24,7 +26,7 @@ public:
~local_free_on_destruction()
{
- ::LocalFree(p_);
+ boost::detail::winapi::LocalFree(p_);
}
private:
diff --git a/boost/system/error_code.hpp b/boost/system/error_code.hpp
index b6ff6e4bad..0d64b2b72e 100644
--- a/boost/system/error_code.hpp
+++ b/boost/system/error_code.hpp
@@ -1,4 +1,4 @@
-// boost/system/error_code.hpp ---------------------------------------------//
+// boost/system/error_code.hpp -------------------------------------------------------//
// Copyright Beman Dawes 2006, 2007
// Copyright Christoper Kohlhoff 2007
@@ -28,6 +28,10 @@
# error BOOST_POSIX_API or BOOST_WINDOWS_API must be defined
#endif
+#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR
+#include <system_error>
+#endif
+
#include <boost/config/abi_prefix.hpp> // must be the last #include
#ifndef BOOST_SYSTEM_NOEXCEPT
@@ -43,7 +47,7 @@ namespace boost
class error_condition; // portable generic values defined below, but ultimately
// based on the POSIX standard
- // "Concept" helpers ---------------------------------------------------//
+ // "Concept" helpers -------------------------------------------------------------//
template< class T >
struct is_error_code_enum { static const bool value = false; };
@@ -51,7 +55,7 @@ namespace boost
template< class T >
struct is_error_condition_enum { static const bool value = false; };
- // generic error_conditions --------------------------------------------//
+ // generic error_conditions ------------------------------------------------------//
namespace errc
{
@@ -149,9 +153,9 @@ namespace boost
{ static const bool value = true; };
- // ----------------------------------------------------------------------//
+ // --------------------------------------------------------------------------------//
- // Operating system specific interfaces --------------------------------//
+ // Operating system specific interfaces ------------------------------------------//
// The interface is divided into general and system-specific portions to
@@ -179,52 +183,152 @@ namespace boost
// These headers are effectively empty for compiles on operating systems
// where they are not applicable.
- // ----------------------------------------------------------------------//
+ // --------------------------------------------------------------------------------//
+
+ class error_category;
+
+ // predefined error categories ---------------------------------------------------//
+
+#ifdef BOOST_ERROR_CODE_HEADER_ONLY
+ inline const error_category & system_category() BOOST_SYSTEM_NOEXCEPT;
+ inline const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT;
+#else
+ BOOST_SYSTEM_DECL const error_category & system_category() BOOST_SYSTEM_NOEXCEPT;
+ BOOST_SYSTEM_DECL const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT;
+#endif
+ // deprecated synonyms ------------------------------------------------------------//
+
+#ifndef BOOST_SYSTEM_NO_DEPRECATED
+ inline const error_category & get_system_category() { return system_category(); }
+ inline const error_category & get_generic_category() { return generic_category(); }
+ inline const error_category & get_posix_category() { return generic_category(); }
+ static const error_category & posix_category BOOST_ATTRIBUTE_UNUSED
+ = generic_category();
+ static const error_category & errno_ecat BOOST_ATTRIBUTE_UNUSED
+ = generic_category();
+ static const error_category & native_ecat BOOST_ATTRIBUTE_UNUSED
+ = system_category();
+#endif
// class error_category ------------------------------------------------//
class error_category : public noncopyable
{
+#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR
+
+ private:
+
+ class std_category: public std::error_category
+ {
+ private:
+
+ boost::system::error_category const * pc_;
+
+ public:
+
+ explicit std_category( boost::system::error_category const * pc ): pc_( pc )
+ {
+ }
+
+ virtual const char * name() const BOOST_NOEXCEPT
+ {
+ return pc_->name();
+ }
+
+ virtual std::string message( int ev ) const
+ {
+ return pc_->message( ev );
+ }
+
+ virtual std::error_condition default_error_condition( int ev ) const
+ BOOST_NOEXCEPT;
+ virtual bool equivalent( int code, const std::error_condition & condition ) const
+ BOOST_NOEXCEPT;
+ virtual bool equivalent( const std::error_code & code, int condition ) const
+ BOOST_NOEXCEPT;
+ };
+
+ std_category std_cat_;
+
+ public:
+
+ error_category() BOOST_SYSTEM_NOEXCEPT: std_cat_( this ) {}
+
+ operator std::error_category const & () const BOOST_SYSTEM_NOEXCEPT
+ {
+ // do not map generic to std::generic on purpose; occasionally,
+ // there are two std::generic categories in a program, which leads
+ // to error codes/conditions mysteriously not being equal to themselves
+ return std_cat_;
+ }
+
+#else
+
+ // to maintain ABI compatibility between 03 and 11,
+ // define a class with the same layout
+
+ private:
+
+ class std_category
+ {
+ private:
+
+ boost::system::error_category const * pc_;
+
+ public:
+
+ explicit std_category( boost::system::error_category const * pc ): pc_( pc )
+ {
+ }
+
+ virtual ~std_category() {}
+
+ virtual const char * name() const BOOST_NOEXCEPT
+ {
+ return pc_->name();
+ }
+
+ // we can't define message, because (1) it returns an std::string,
+ // which can be different between 03 and 11, and (2) on mingw, there
+ // are actually two `message` functions, not one, so it doesn't work
+ // even if we do
+
+ // neither can we define default_error_condition or equivalent
+
+ // if these functions are called, it will crash, but that's still
+ // better than the alternative of having the class layout change
+ };
+
+ std_category std_cat_;
+
+ public:
+
+ error_category() BOOST_SYSTEM_NOEXCEPT: std_cat_( this ) {}
+
+#endif
+
public:
virtual ~error_category(){}
virtual const char * name() const BOOST_SYSTEM_NOEXCEPT = 0;
virtual std::string message( int ev ) const = 0;
- inline virtual error_condition default_error_condition( int ev ) const BOOST_SYSTEM_NOEXCEPT;
+ inline virtual error_condition default_error_condition( int ev ) const
+ BOOST_SYSTEM_NOEXCEPT;
inline virtual bool equivalent( int code,
- const error_condition & condition ) const BOOST_SYSTEM_NOEXCEPT;
+ const error_condition & condition ) const
+ BOOST_SYSTEM_NOEXCEPT;
inline virtual bool equivalent( const error_code & code,
int condition ) const BOOST_SYSTEM_NOEXCEPT;
- bool operator==(const error_category & rhs) const BOOST_SYSTEM_NOEXCEPT { return this == &rhs; }
- bool operator!=(const error_category & rhs) const BOOST_SYSTEM_NOEXCEPT { return this != &rhs; }
+ bool operator==(const error_category & rhs) const BOOST_SYSTEM_NOEXCEPT
+ { return this == &rhs; }
+ bool operator!=(const error_category & rhs) const BOOST_SYSTEM_NOEXCEPT
+ { return this != &rhs; }
bool operator<( const error_category & rhs ) const BOOST_SYSTEM_NOEXCEPT
- {
- return std::less<const error_category*>()( this, &rhs );
- }
+ { return std::less<const error_category*>()( this, &rhs ); }
};
- // predefined error categories -----------------------------------------//
-
-# ifdef BOOST_ERROR_CODE_HEADER_ONLY
- inline const error_category & system_category() BOOST_SYSTEM_NOEXCEPT;
- inline const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT;
-#else
- BOOST_SYSTEM_DECL const error_category & system_category() BOOST_SYSTEM_NOEXCEPT;
- BOOST_SYSTEM_DECL const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT;
-#endif
- // deprecated synonyms --------------------------------------------------//
-
-# ifndef BOOST_SYSTEM_NO_DEPRECATED
- inline const error_category & get_system_category() { return system_category(); }
- inline const error_category & get_generic_category() { return generic_category(); }
- inline const error_category & get_posix_category() { return generic_category(); }
- static const error_category & posix_category BOOST_ATTRIBUTE_UNUSED = generic_category();
- static const error_category & errno_ecat BOOST_ATTRIBUTE_UNUSED = generic_category();
- static const error_category & native_ecat BOOST_ATTRIBUTE_UNUSED = system_category();
-# endif
-
- // class error_condition -----------------------------------------------//
+ // class error_condition ---------------------------------------------------------//
// error_conditions are portable, error_codes are system or library specific
@@ -234,11 +338,13 @@ namespace boost
// constructors:
error_condition() BOOST_SYSTEM_NOEXCEPT : m_val(0), m_cat(&generic_category()) {}
- error_condition( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT : m_val(val), m_cat(&cat) {}
+ error_condition( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT
+ : m_val(val), m_cat(&cat) {}
template <class ErrorConditionEnum>
error_condition(ErrorConditionEnum e,
- typename boost::enable_if<is_error_condition_enum<ErrorConditionEnum> >::type* = 0) BOOST_SYSTEM_NOEXCEPT
+ typename boost::enable_if<is_error_condition_enum<ErrorConditionEnum> >::type*
+ = 0) BOOST_SYSTEM_NOEXCEPT
{
*this = make_error_condition(e);
}
@@ -252,7 +358,8 @@ namespace boost
}
template<typename ErrorConditionEnum>
- typename boost::enable_if<is_error_condition_enum<ErrorConditionEnum>, error_condition>::type &
+ typename boost::enable_if<is_error_condition_enum<ErrorConditionEnum>,
+ error_condition>::type &
operator=( ErrorConditionEnum val ) BOOST_SYSTEM_NOEXCEPT
{
*this = make_error_condition(val);
@@ -301,13 +408,22 @@ namespace boost
|| (lhs.m_cat == rhs.m_cat && lhs.m_val < rhs.m_val);
}
+#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR
+
+ operator std::error_condition () const BOOST_SYSTEM_NOEXCEPT
+ {
+ return std::error_condition( value(), category() );
+ }
+
+#endif
+
private:
int m_val;
const error_category * m_cat;
};
- // class error_code ----------------------------------------------------//
+ // class error_code --------------------------------------------------------------//
// We want error_code to be a value type that can be copied without slicing
// and without requiring heap allocation, but we also want it to have
@@ -321,11 +437,13 @@ namespace boost
// constructors:
error_code() BOOST_SYSTEM_NOEXCEPT : m_val(0), m_cat(&system_category()) {}
- error_code( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT : m_val(val), m_cat(&cat) {}
+ error_code( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT
+ : m_val(val), m_cat(&cat) {}
template <class ErrorCodeEnum>
error_code(ErrorCodeEnum e,
- typename boost::enable_if<is_error_code_enum<ErrorCodeEnum> >::type* = 0) BOOST_SYSTEM_NOEXCEPT
+ typename boost::enable_if<is_error_code_enum<ErrorCodeEnum> >::type* = 0)
+ BOOST_SYSTEM_NOEXCEPT
{
*this = make_error_code(e);
}
@@ -354,7 +472,8 @@ namespace boost
// observers:
int value() const BOOST_SYSTEM_NOEXCEPT { return m_val; }
const error_category & category() const BOOST_SYSTEM_NOEXCEPT { return *m_cat; }
- error_condition default_error_condition() const BOOST_SYSTEM_NOEXCEPT { return m_cat->default_error_condition(value()); }
+ error_condition default_error_condition() const BOOST_SYSTEM_NOEXCEPT
+ { return m_cat->default_error_condition(value()); }
std::string message() const { return m_cat->message(value()); }
typedef void (*unspecified_bool_type)();
@@ -388,6 +507,15 @@ namespace boost
|| (lhs.m_cat == rhs.m_cat && lhs.m_val < rhs.m_val);
}
+#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR
+
+ operator std::error_code () const BOOST_SYSTEM_NOEXCEPT
+ {
+ return std::error_code( value(), category() );
+ }
+
+#endif
+
private:
int m_val;
const error_category * m_cat;
@@ -475,7 +603,7 @@ namespace boost
+ reinterpret_cast<std::size_t>(&ec.category());
}
- // make_* functions for errc::errc_t -----------------------------//
+ // make_* functions for errc::errc_t ---------------------------------------------//
namespace errc
{
@@ -488,9 +616,10 @@ namespace boost
{ return error_condition( e, generic_category() ); }
}
- // error_category default implementation -------------------------------//
+ // error_category default implementation -----------------------------------------//
- error_condition error_category::default_error_condition( int ev ) const BOOST_SYSTEM_NOEXCEPT
+ error_condition error_category::default_error_condition( int ev ) const
+ BOOST_SYSTEM_NOEXCEPT
{
return error_condition( ev, *this );
}
@@ -507,6 +636,80 @@ namespace boost
return *this == code.category() && code.value() == condition;
}
+#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR
+
+ inline std::error_condition error_category::std_category::default_error_condition(
+ int ev ) const BOOST_NOEXCEPT
+ {
+ return pc_->default_error_condition( ev );
+ }
+
+ inline bool error_category::std_category::equivalent( int code,
+ const std::error_condition & condition ) const BOOST_NOEXCEPT
+ {
+ if( condition.category() == *this )
+ {
+ boost::system::error_condition bn( condition.value(), *pc_ );
+ return pc_->equivalent( code, bn );
+ }
+ else if( condition.category() == std::generic_category()
+ || condition.category() == boost::system::generic_category() )
+ {
+ boost::system::error_condition bn( condition.value(),
+ boost::system::generic_category() );
+
+ return pc_->equivalent( code, bn );
+ }
+#ifndef BOOST_NO_RTTI
+ else if( std_category const* pc2 = dynamic_cast< std_category const* >(
+ &condition.category() ) )
+ {
+ boost::system::error_condition bn( condition.value(), *pc2->pc_ );
+ return pc_->equivalent( code, bn );
+ }
+#endif
+ else
+ {
+ return default_error_condition( code ) == condition;
+ }
+ }
+
+ inline bool error_category::std_category::equivalent( const std::error_code & code,
+ int condition ) const BOOST_NOEXCEPT
+ {
+ if( code.category() == *this )
+ {
+ boost::system::error_code bc( code.value(), *pc_ );
+ return pc_->equivalent( bc, condition );
+ }
+ else if( code.category() == std::generic_category()
+ || code.category() == boost::system::generic_category() )
+ {
+ boost::system::error_code bc( code.value(),
+ boost::system::generic_category() );
+
+ return pc_->equivalent( bc, condition );
+ }
+#ifndef BOOST_NO_RTTI
+ else if( std_category const* pc2 = dynamic_cast< std_category const* >(
+ &code.category() ) )
+ {
+ boost::system::error_code bc( code.value(), *pc2->pc_ );
+ return pc_->equivalent( bc, condition );
+ }
+#endif
+ else if( *pc_ == boost::system::generic_category() )
+ {
+ return std::generic_category().equivalent( code, condition );
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+#endif
+
} // namespace system
} // namespace boost
@@ -517,5 +720,3 @@ namespace boost
# endif
#endif // BOOST_SYSTEM_ERROR_CODE_HPP
-
-
diff --git a/boost/system/system_error.hpp b/boost/system/system_error.hpp
index d98b4bcf84..c5e7e402ba 100644
--- a/boost/system/system_error.hpp
+++ b/boost/system/system_error.hpp
@@ -44,10 +44,10 @@ namespace boost
const char * what_arg )
: std::runtime_error(what_arg), m_error_code(ev,ecat) {}
- virtual ~system_error() throw() {}
+ virtual ~system_error() BOOST_NOEXCEPT_OR_NOTHROW {}
- const error_code & code() const throw() { return m_error_code; }
- const char * what() const throw();
+ const error_code & code() const BOOST_NOEXCEPT_OR_NOTHROW { return m_error_code; }
+ const char * what() const BOOST_NOEXCEPT_OR_NOTHROW;
private:
error_code m_error_code;
@@ -56,7 +56,7 @@ namespace boost
// implementation ------------------------------------------------------//
- inline const char * system_error::what() const throw()
+ inline const char * system_error::what() const BOOST_NOEXCEPT_OR_NOTHROW
// see http://www.boost.org/more/error_handling.html for lazy build rationale
{
if ( m_what.empty() )
diff --git a/boost/system/windows_error.hpp b/boost/system/windows_error.hpp
index 38d628404c..0fb7ea6352 100644
--- a/boost/system/windows_error.hpp
+++ b/boost/system/windows_error.hpp
@@ -19,14 +19,16 @@
#include <boost/system/error_code.hpp>
-// Neither MinGW or Cygwin versions of winerror.h work if used alone, so on
-// either of those platforms include the full windows.h
+//// Neither MinGW or Cygwin versions of winerror.h work if used alone, so on
+//// either of those platforms include the full windows.h
+//
+//#if defined(__MINGW32__) || defined(__CYGWIN__)
+//#include <windows.h>
+//#else
+//#include <winerror.h>
+//#endif
-#if defined(__MINGW32__) || defined(__CYGWIN__)
-#include <windows.h>
-#else
-#include <winerror.h>
-#endif
+#include <boost/detail/winapi/error_codes.hpp>
namespace boost
{
@@ -45,59 +47,59 @@ namespace boost
{
success = 0,
// These names and values are based on Windows winerror.h
- invalid_function = ERROR_INVALID_FUNCTION,
- file_not_found = ERROR_FILE_NOT_FOUND,
- path_not_found = ERROR_PATH_NOT_FOUND,
- too_many_open_files = ERROR_TOO_MANY_OPEN_FILES,
- access_denied = ERROR_ACCESS_DENIED,
- invalid_handle = ERROR_INVALID_HANDLE,
- arena_trashed = ERROR_ARENA_TRASHED,
- not_enough_memory = ERROR_NOT_ENOUGH_MEMORY,
- invalid_block = ERROR_INVALID_BLOCK,
- bad_environment = ERROR_BAD_ENVIRONMENT,
- bad_format = ERROR_BAD_FORMAT,
- invalid_access = ERROR_INVALID_ACCESS,
- outofmemory = ERROR_OUTOFMEMORY,
- invalid_drive = ERROR_INVALID_DRIVE,
- current_directory = ERROR_CURRENT_DIRECTORY,
- not_same_device = ERROR_NOT_SAME_DEVICE,
- no_more_files = ERROR_NO_MORE_FILES,
- write_protect = ERROR_WRITE_PROTECT,
- bad_unit = ERROR_BAD_UNIT,
- not_ready = ERROR_NOT_READY,
- bad_command = ERROR_BAD_COMMAND,
- crc = ERROR_CRC,
- bad_length = ERROR_BAD_LENGTH,
- seek = ERROR_SEEK,
- not_dos_disk = ERROR_NOT_DOS_DISK,
- sector_not_found = ERROR_SECTOR_NOT_FOUND,
- out_of_paper = ERROR_OUT_OF_PAPER,
- write_fault = ERROR_WRITE_FAULT,
- read_fault = ERROR_READ_FAULT,
- gen_failure = ERROR_GEN_FAILURE,
- sharing_violation = ERROR_SHARING_VIOLATION,
- lock_violation = ERROR_LOCK_VIOLATION,
- wrong_disk = ERROR_WRONG_DISK,
- sharing_buffer_exceeded = ERROR_SHARING_BUFFER_EXCEEDED,
- handle_eof = ERROR_HANDLE_EOF,
- handle_disk_full= ERROR_HANDLE_DISK_FULL,
- rem_not_list = ERROR_REM_NOT_LIST,
- dup_name = ERROR_DUP_NAME,
- bad_net_path = ERROR_BAD_NETPATH,
- network_busy = ERROR_NETWORK_BUSY,
+ invalid_function = boost::detail::winapi::ERROR_INVALID_FUNCTION_,
+ file_not_found = boost::detail::winapi::ERROR_FILE_NOT_FOUND_,
+ path_not_found = boost::detail::winapi::ERROR_PATH_NOT_FOUND_,
+ too_many_open_files = boost::detail::winapi::ERROR_TOO_MANY_OPEN_FILES_,
+ access_denied = boost::detail::winapi::ERROR_ACCESS_DENIED_,
+ invalid_handle = boost::detail::winapi::ERROR_INVALID_HANDLE_,
+ arena_trashed = boost::detail::winapi::ERROR_ARENA_TRASHED_,
+ not_enough_memory = boost::detail::winapi::ERROR_NOT_ENOUGH_MEMORY_,
+ invalid_block = boost::detail::winapi::ERROR_INVALID_BLOCK_,
+ bad_environment = boost::detail::winapi::ERROR_BAD_ENVIRONMENT_,
+ bad_format = boost::detail::winapi::ERROR_BAD_FORMAT_,
+ invalid_access = boost::detail::winapi::ERROR_INVALID_ACCESS_,
+ outofmemory = boost::detail::winapi::ERROR_OUTOFMEMORY_,
+ invalid_drive = boost::detail::winapi::ERROR_INVALID_DRIVE_,
+ current_directory = boost::detail::winapi::ERROR_CURRENT_DIRECTORY_,
+ not_same_device = boost::detail::winapi::ERROR_NOT_SAME_DEVICE_,
+ no_more_files = boost::detail::winapi::ERROR_NO_MORE_FILES_,
+ write_protect = boost::detail::winapi::ERROR_WRITE_PROTECT_,
+ bad_unit = boost::detail::winapi::ERROR_BAD_UNIT_,
+ not_ready = boost::detail::winapi::ERROR_NOT_READY_,
+ bad_command = boost::detail::winapi::ERROR_BAD_COMMAND_,
+ crc = boost::detail::winapi::ERROR_CRC_,
+ bad_length = boost::detail::winapi::ERROR_BAD_LENGTH_,
+ seek = boost::detail::winapi::ERROR_SEEK_,
+ not_dos_disk = boost::detail::winapi::ERROR_NOT_DOS_DISK_,
+ sector_not_found = boost::detail::winapi::ERROR_SECTOR_NOT_FOUND_,
+ out_of_paper = boost::detail::winapi::ERROR_OUT_OF_PAPER_,
+ write_fault = boost::detail::winapi::ERROR_WRITE_FAULT_,
+ read_fault = boost::detail::winapi::ERROR_READ_FAULT_,
+ gen_failure = boost::detail::winapi::ERROR_GEN_FAILURE_,
+ sharing_violation = boost::detail::winapi::ERROR_SHARING_VIOLATION_,
+ lock_violation = boost::detail::winapi::ERROR_LOCK_VIOLATION_,
+ wrong_disk = boost::detail::winapi::ERROR_WRONG_DISK_,
+ sharing_buffer_exceeded = boost::detail::winapi::ERROR_SHARING_BUFFER_EXCEEDED_,
+ handle_eof = boost::detail::winapi::ERROR_HANDLE_EOF_,
+ handle_disk_full= boost::detail::winapi::ERROR_HANDLE_DISK_FULL_,
+ rem_not_list = boost::detail::winapi::ERROR_REM_NOT_LIST_,
+ dup_name = boost::detail::winapi::ERROR_DUP_NAME_,
+ bad_net_path = boost::detail::winapi::ERROR_BAD_NETPATH_,
+ network_busy = boost::detail::winapi::ERROR_NETWORK_BUSY_,
// ...
- file_exists = ERROR_FILE_EXISTS,
- cannot_make = ERROR_CANNOT_MAKE,
+ file_exists = boost::detail::winapi::ERROR_FILE_EXISTS_,
+ cannot_make = boost::detail::winapi::ERROR_CANNOT_MAKE_,
// ...
- broken_pipe = ERROR_BROKEN_PIPE,
- open_failed = ERROR_OPEN_FAILED,
- buffer_overflow = ERROR_BUFFER_OVERFLOW,
- disk_full= ERROR_DISK_FULL,
+ broken_pipe = boost::detail::winapi::ERROR_BROKEN_PIPE_,
+ open_failed = boost::detail::winapi::ERROR_OPEN_FAILED_,
+ buffer_overflow = boost::detail::winapi::ERROR_BUFFER_OVERFLOW_,
+ disk_full= boost::detail::winapi::ERROR_DISK_FULL_,
// ...
- lock_failed = ERROR_LOCK_FAILED,
- busy = ERROR_BUSY,
- cancel_violation = ERROR_CANCEL_VIOLATION,
- already_exists = ERROR_ALREADY_EXISTS
+ lock_failed = boost::detail::winapi::ERROR_LOCK_FAILED_,
+ busy = boost::detail::winapi::ERROR_BUSY_,
+ cancel_violation = boost::detail::winapi::ERROR_CANCEL_VIOLATION_,
+ already_exists = boost::detail::winapi::ERROR_ALREADY_EXISTS_
// ...
// TODO: add more Windows errors
diff --git a/boost/test/data/monomorphic/collection.hpp b/boost/test/data/monomorphic/collection.hpp
index 49e81458bf..71a4863f41 100644
--- a/boost/test/data/monomorphic/collection.hpp
+++ b/boost/test/data/monomorphic/collection.hpp
@@ -75,7 +75,7 @@ struct is_dataset<collection<C>> : mpl::true_ {};
//! @overload boost::unit_test::data::make()
template<typename C>
-inline typename std::enable_if<is_forward_iterable<C>::value,monomorphic::collection<C>>::type
+inline typename std::enable_if<is_container_forward_iterable<C>::value,monomorphic::collection<C>>::type
make( C&& c )
{
return monomorphic::collection<C>( std::forward<C>(c) );
diff --git a/boost/test/data/monomorphic/fwd.hpp b/boost/test/data/monomorphic/fwd.hpp
index cf6d3b0000..dcd1b84165 100644
--- a/boost/test/data/monomorphic/fwd.hpp
+++ b/boost/test/data/monomorphic/fwd.hpp
@@ -119,7 +119,7 @@ make(DataSet&& ds)
//! @overload boost::unit_test::data::make()
template<typename T>
-inline typename std::enable_if<!is_forward_iterable<T>::value &&
+inline typename std::enable_if<!is_container_forward_iterable<T>::value &&
!monomorphic::is_dataset<T>::value &&
!is_array<typename remove_reference<T>::type>::value,
monomorphic::singleton<T>>::type
@@ -129,7 +129,7 @@ make( T&& v );
//! @overload boost::unit_test::data::make()
template<typename C>
-inline typename std::enable_if<is_forward_iterable<C>::value,monomorphic::collection<C>>::type
+inline typename std::enable_if<is_container_forward_iterable<C>::value,monomorphic::collection<C>>::type
make( C&& c );
//____________________________________________________________________________//
diff --git a/boost/test/data/monomorphic/generate.hpp b/boost/test/data/monomorphic/generate.hpp
index af3b5c0bb9..614ef3aad5 100644
--- a/boost/test/data/monomorphic/generate.hpp
+++ b/boost/test/data/monomorphic/generate.hpp
@@ -16,6 +16,8 @@
#include <boost/test/data/config.hpp>
#include <boost/test/data/monomorphic/fwd.hpp>
+#include <boost/core/ref.hpp>
+
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
diff --git a/boost/test/data/monomorphic/grid.hpp b/boost/test/data/monomorphic/grid.hpp
index 3e1b36abad..2cf66189a0 100644
--- a/boost/test/data/monomorphic/grid.hpp
+++ b/boost/test/data/monomorphic/grid.hpp
@@ -22,6 +22,8 @@
#include <boost/test/data/monomorphic/fwd.hpp>
#include <boost/test/data/monomorphic/sample_merge.hpp>
+#include <boost/mpl/identity.hpp>
+
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
diff --git a/boost/test/data/monomorphic/singleton.hpp b/boost/test/data/monomorphic/singleton.hpp
index 586487a6d7..b0abd0eabb 100644
--- a/boost/test/data/monomorphic/singleton.hpp
+++ b/boost/test/data/monomorphic/singleton.hpp
@@ -81,7 +81,7 @@ struct is_dataset<singleton<T>> : mpl::true_ {};
/// @overload boost::unit_test::data::make()
template<typename T>
-inline typename std::enable_if<!is_forward_iterable<T>::value &&
+inline typename std::enable_if<!is_container_forward_iterable<T>::value &&
!monomorphic::is_dataset<T>::value &&
!boost::is_array<typename boost::remove_reference<T>::type>::value,
monomorphic::singleton<T>
diff --git a/boost/test/data/test_case.hpp b/boost/test/data/test_case.hpp
index dd9de141c4..2275f90fff 100644
--- a/boost/test/data/test_case.hpp
+++ b/boost/test/data/test_case.hpp
@@ -16,6 +16,7 @@
#include <boost/test/data/config.hpp>
#include <boost/test/data/dataset.hpp>
#include <boost/test/data/for_each_sample.hpp>
+#include <boost/test/tree/test_unit.hpp>
// Boost
#include <boost/preprocessor/repetition/enum_params.hpp>
diff --git a/boost/test/detail/fwd_decl.hpp b/boost/test/detail/fwd_decl.hpp
index 944d52267d..d5c97fb706 100644
--- a/boost/test/detail/fwd_decl.hpp
+++ b/boost/test/detail/fwd_decl.hpp
@@ -26,6 +26,7 @@ class master_test_suite_t;
class test_tree_visitor;
class test_observer;
+class test_unit_fixture;
// singletons
class unit_test_monitor_t;
diff --git a/boost/test/detail/global_typedef.hpp b/boost/test/detail/global_typedef.hpp
index b9cfeb5206..aeede00e9c 100644
--- a/boost/test/detail/global_typedef.hpp
+++ b/boost/test/detail/global_typedef.hpp
@@ -71,6 +71,21 @@ test_id_2_unit_type( test_unit_id id )
return (id & 0xFFFF0000) != 0 ? TUT_CASE : TUT_SUITE;
}
+//! Helper class for restoring the current test unit ID in a RAII manner
+struct test_unit_id_restore {
+ test_unit_id_restore(test_unit_id& to_restore_, test_unit_id new_value)
+ : to_restore(to_restore_)
+ , bkup(to_restore_) {
+ to_restore = new_value;
+ }
+ ~test_unit_id_restore() {
+ to_restore = bkup;
+ }
+private:
+ test_unit_id& to_restore;
+ test_unit_id bkup;
+};
+
//____________________________________________________________________________//
} // namespace ut_detail
diff --git a/boost/test/execution_monitor.hpp b/boost/test/execution_monitor.hpp
index adfb0336ca..ed06ef254e 100644
--- a/boost/test/execution_monitor.hpp
+++ b/boost/test/execution_monitor.hpp
@@ -270,6 +270,7 @@ public:
/// Simple model for the location of failure in a source code
struct BOOST_TEST_DECL location {
explicit location( char const* file_name = 0, size_t line_num = 0, char const* func = 0 );
+ explicit location( const_string file_name, size_t line_num = 0, char const* func = 0 );
const_string m_file_name; ///< File name
size_t m_line_num; ///< Line number
diff --git a/boost/test/framework.hpp b/boost/test/framework.hpp
index f94bcf125d..099c02969b 100644
--- a/boost/test/framework.hpp
+++ b/boost/test/framework.hpp
@@ -74,7 +74,7 @@ BOOST_TEST_DECL bool test_in_progress();
/// This function shuts down the framework and clears up its mono-state.
///
/// It needs to be at the very end of test module execution
-BOOST_TEST_DECL void shutdown();
+BOOST_TEST_DECL void shutdown();
/// @}
/// @name Test unit registration
@@ -132,12 +132,28 @@ BOOST_TEST_DECL void clear();
/// @param[in] to test observer object to add
BOOST_TEST_DECL void register_observer( test_observer& to );
-/// Excldes the observer object form the framework's list of test observers
+/// Excludes the observer object form the framework's list of test observers
/// @param[in] to test observer object to exclude
BOOST_TEST_DECL void deregister_observer( test_observer& to );
/// @}
+/// @name Global fixtures registration
+/// @{
+
+/// Adds a new global fixture to be setup before any other tests starts and tore down after
+/// any other tests finished.
+/// Test unit fixture lifetime should exceed the testing execution timeframe
+/// @param[in] tuf fixture to add
+BOOST_TEST_DECL void register_global_fixture( test_unit_fixture& tuf );
+
+/// Removes a test global fixture from the framework
+///
+/// Test unit fixture lifetime should exceed the testing execution timeframe
+/// @param[in] tuf fixture to remove
+BOOST_TEST_DECL void deregister_global_fixture( test_unit_fixture& tuf );
+/// @}
+
/// @name Assertion/uncaught exception context support
/// @{
/// Context accessor
@@ -178,6 +194,15 @@ BOOST_TEST_DECL context_generator get_context();
/// @returns a reference the master test suite instance
BOOST_TEST_DECL master_test_suite_t& master_test_suite();
+/// This function provides an access to the test unit currently being executed.
+
+/// The difference with current_test_case is about the time between a test-suite
+/// is being set up or torn down (fixtures) and when the test-cases of that suite start.
+
+/// This function is only valid during test execution phase.
+/// @see current_test_case_id, current_test_case
+BOOST_TEST_DECL test_unit const& current_test_unit();
+
/// This function provides an access to the test case currently being executed.
/// This function is only valid during test execution phase.
@@ -231,6 +256,8 @@ BOOST_TEST_DECL void assertion_result( unit_test::assertion_resul
BOOST_TEST_DECL void exception_caught( execution_exception const& );
/// Reports aborted test unit to all test observers
BOOST_TEST_DECL void test_unit_aborted( test_unit const& );
+/// Reports aborted test module to all test observers
+BOOST_TEST_DECL void test_aborted( );
/// @}
namespace impl {
diff --git a/boost/test/impl/compiler_log_formatter.ipp b/boost/test/impl/compiler_log_formatter.ipp
index a4e045cae0..0e83448b14 100644
--- a/boost/test/impl/compiler_log_formatter.ipp
+++ b/boost/test/impl/compiler_log_formatter.ipp
@@ -52,7 +52,7 @@ namespace {
std::string
test_phase_identifier()
{
- return framework::test_in_progress() ? framework::current_test_case().full_name() : std::string( "Test setup" );
+ return framework::test_in_progress() ? framework::current_test_unit().full_name() : std::string( "Test setup" );
}
} // local namespace
@@ -260,21 +260,29 @@ compiler_log_formatter::print_prefix( std::ostream& output, const_string file_na
void
compiler_log_formatter::entry_context_start( std::ostream& output, log_level l )
{
- output << (l == log_successful_tests ? "\nAssertion" : "\nFailure" ) << " occurred in a following context:";
+ if( l == log_messages ) {
+ output << "\n[context:";
+ }
+ else {
+ output << (l == log_successful_tests ? "\nAssertion" : "\nFailure" ) << " occurred in a following context:";
+ }
}
//____________________________________________________________________________//
void
-compiler_log_formatter::entry_context_finish( std::ostream& output )
+compiler_log_formatter::entry_context_finish( std::ostream& output, log_level l )
{
+ if( l == log_messages ) {
+ output << "]";
+ }
output.flush();
}
//____________________________________________________________________________//
void
-compiler_log_formatter::log_entry_context( std::ostream& output, const_string context_descr )
+compiler_log_formatter::log_entry_context( std::ostream& output, log_level l, const_string context_descr )
{
output << "\n " << context_descr;
}
diff --git a/boost/test/impl/execution_monitor.ipp b/boost/test/impl/execution_monitor.ipp
index 0c5690ca89..94b6f9fbe7 100644
--- a/boost/test/impl/execution_monitor.ipp
+++ b/boost/test/impl/execution_monitor.ipp
@@ -1342,6 +1342,12 @@ execution_exception::location::location( char const* file_name, size_t line_num,
, m_function( func )
{}
+execution_exception::location::location(const_string file_name, size_t line_num, char const* func )
+: m_file_name( file_name )
+, m_line_num( line_num )
+, m_function( func )
+{}
+
//____________________________________________________________________________//
// ************************************************************************** //
diff --git a/boost/test/impl/framework.ipp b/boost/test/impl/framework.ipp
index a35e8a54ac..ca35ce1c2a 100644
--- a/boost/test/impl/framework.ipp
+++ b/boost/test/impl/framework.ipp
@@ -27,6 +27,7 @@
#include <boost/test/results_collector.hpp>
#include <boost/test/progress_monitor.hpp>
#include <boost/test/results_reporter.hpp>
+#include <boost/test/test_framework_init_observer.hpp>
#include <boost/test/tree/observer.hpp>
#include <boost/test/tree/test_unit.hpp>
@@ -56,6 +57,9 @@
#include <cstdlib>
#include <ctime>
#include <numeric>
+#ifdef BOOST_NO_CXX98_RANDOM_SHUFFLE
+#include <iterator>
+#endif
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::time; using ::srand; }
@@ -68,6 +72,7 @@ namespace std { using ::time; using ::srand; }
namespace boost {
namespace unit_test {
namespace framework {
+
namespace impl {
// ************************************************************************** //
@@ -435,6 +440,46 @@ parse_filters( test_unit_id master_tu_id, test_unit_id_list& tu_to_enable, test_
//____________________________________________________________________________//
+#ifdef BOOST_NO_CXX98_RANDOM_SHUFFLE
+
+// a poor man's implementation of random_shuffle
+template< class RandomIt, class RandomFunc >
+void random_shuffle( RandomIt first, RandomIt last, RandomFunc &r )
+{
+ typedef typename std::iterator_traits<RandomIt>::difference_type difference_type;
+ difference_type n = last - first;
+ for (difference_type i = n-1; i > 0; --i) {
+ difference_type j = r(i+1);
+ if (j != i) {
+ using std::swap;
+ swap(first[i], first[j]);
+ }
+ }
+}
+
+#endif
+
+
+// A simple handle for registering the global fixtures to the master test suite
+// without deleting an existing static object (the global fixture itself) when the program
+// terminates (shared_ptr).
+class global_fixture_handle : public test_unit_fixture {
+public:
+ global_fixture_handle(test_unit_fixture* fixture) : m_global_fixture(fixture) {}
+ ~global_fixture_handle() {}
+
+ virtual void setup() {
+ m_global_fixture->setup();
+ }
+ virtual void teardown() {
+ m_global_fixture->teardown();
+ }
+
+private:
+ test_unit_fixture* m_global_fixture;
+};
+
+
} // namespace impl
// ************************************************************************** //
@@ -446,7 +491,7 @@ unsigned const TIMEOUT_EXCEEDED = static_cast<unsigned>( -1 );
class state {
public:
state()
- : m_curr_test_case( INV_TEST_UNIT_ID )
+ : m_curr_test_unit( INV_TEST_UNIT_ID )
, m_next_test_case_id( MIN_TEST_CASE_ID )
, m_next_test_suite_id( MIN_TEST_SUITE_ID )
, m_test_in_progress( false )
@@ -603,7 +648,7 @@ public:
}
};
- // Executed the test tree with the root at specified test unit
+ // Executes the test tree with the root at specified test unit
execution_result execute_test_tree( test_unit_id tu_id,
unsigned timeout = 0,
random_generator_helper const * const p_random_generator = 0)
@@ -642,9 +687,15 @@ public:
// 30. Execute setup fixtures if any; any failure here leads to test unit abortion
BOOST_TEST_FOREACH( test_unit_fixture_ptr, F, tu.p_fixtures.get() ) {
+ ut_detail::test_unit_id_restore restore_current_test_unit(m_curr_test_unit, tu.p_id);
result = unit_test_monitor.execute_and_translate( boost::bind( &test_unit_fixture::setup, F ) );
if( result != unit_test_monitor_t::test_ok )
break;
+ test_results const& test_rslt = unit_test::results_collector.results( m_curr_test_unit );
+ if( test_rslt.aborted() ) {
+ result = unit_test_monitor_t::precondition_failure;
+ break;
+ }
}
// This is the time we are going to spend executing the test unit
@@ -688,7 +739,11 @@ public:
const random_generator_helper& rand_gen = p_random_generator ? *p_random_generator : random_generator_helper();
+#ifdef BOOST_NO_CXX98_RANDOM_SHUFFLE
+ impl::random_shuffle( children_with_the_same_rank.begin(), children_with_the_same_rank.end(), rand_gen );
+#else
std::random_shuffle( children_with_the_same_rank.begin(), children_with_the_same_rank.end(), rand_gen );
+#endif
BOOST_TEST_FOREACH( test_unit_id, chld, children_with_the_same_rank ) {
unsigned chld_timeout = child_timeout( timeout, tu_timer.elapsed() );
@@ -710,8 +765,7 @@ public:
m_context_idx = 0;
// setup current test case
- test_unit_id bkup = m_curr_test_case;
- m_curr_test_case = tc.p_id;
+ ut_detail::test_unit_id_restore restore_current_test_unit(m_curr_test_unit, tc.p_id);
// execute the test case body
result = unit_test_monitor.execute_and_translate( tc.p_test_func, timeout );
@@ -720,8 +774,7 @@ public:
// cleanup leftover context
m_context.clear();
- // restore state and abort if necessary
- m_curr_test_case = bkup;
+ // restore state (scope exit) and abort if necessary
}
}
@@ -729,6 +782,7 @@ public:
if( !unit_test_monitor.is_critical_error( result ) ) {
// execute teardown fixtures if any in reverse order
BOOST_TEST_REVERSE_FOREACH( test_unit_fixture_ptr, F, tu.p_fixtures.get() ) {
+ ut_detail::test_unit_id_restore restore_current_test_unit(m_curr_test_unit, tu.p_id);
result = (std::min)( result, unit_test_monitor.execute_and_translate( boost::bind( &test_unit_fixture::teardown, F ), 0 ) );
if( unit_test_monitor.is_critical_error( result ) )
@@ -787,7 +841,7 @@ public:
master_test_suite_t* m_master_test_suite;
std::vector<test_suite*> m_auto_test_suites;
- test_unit_id m_curr_test_case;
+ test_unit_id m_curr_test_unit;
test_unit_store m_test_units;
test_unit_id m_next_test_case_id;
@@ -799,6 +853,8 @@ public:
context_data m_context;
int m_context_idx;
+ std::set<test_unit_fixture*> m_global_fixtures;
+
boost::execution_monitor m_aux_em;
std::map<output_format, runtime_config::stream_holder> m_log_sinks;
@@ -1043,6 +1099,7 @@ init( init_unit_test_func init_func, int argc, char* argv[] )
// 40. Register default test observers
register_observer( results_collector );
register_observer( unit_test_log );
+ register_observer( framework_init_observer );
if( runtime_config::get<bool>( runtime_config::btrt_show_progress ) ) {
progress_monitor.set_stream( std::cout ); // defaults to stdout
@@ -1236,6 +1293,30 @@ deregister_observer( test_observer& to )
//____________________________________________________________________________//
// ************************************************************************** //
+// ************** register_global_fixture ************** //
+// ************************************************************************** //
+
+void
+register_global_fixture( test_unit_fixture& tuf )
+{
+ impl::s_frk_state().m_global_fixtures.insert( &tuf );
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** deregister_global_fixture ************** //
+// ************************************************************************** //
+
+void
+deregister_global_fixture( test_unit_fixture &tuf )
+{
+ impl::s_frk_state().m_global_fixtures.erase( &tuf );
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
// ************** add_context ************** //
// ************************************************************************** //
@@ -1363,7 +1444,14 @@ current_auto_test_suite( test_suite* ts, bool push_or_pop )
test_case const&
current_test_case()
{
- return get<test_case>( impl::s_frk_state().m_curr_test_case );
+ return get<test_case>( impl::s_frk_state().m_curr_test_unit );
+}
+
+
+test_unit const&
+current_test_unit()
+{
+ return *impl::s_frk_state().m_test_units[impl::s_frk_state().m_curr_test_unit];
}
//____________________________________________________________________________//
@@ -1371,7 +1459,7 @@ current_test_case()
test_unit_id
current_test_case_id()
{
- return impl::s_frk_state().m_curr_test_case;
+ return impl::s_frk_state().m_curr_test_unit;
}
//____________________________________________________________________________//
@@ -1396,6 +1484,17 @@ get( test_unit_id id, test_unit_type t )
// ************** framework::run ************** //
// ************************************************************************** //
+template <class Cont>
+struct swap_on_delete {
+ swap_on_delete(Cont& c1, Cont& c2) : m_c1(c1), m_c2(c2){}
+ ~swap_on_delete() {
+ m_c1.swap(m_c2);
+ }
+
+ Cont& m_c1;
+ Cont& m_c2;
+};
+
void
run( test_unit_id id, bool continue_test )
{
@@ -1414,39 +1513,90 @@ run( test_unit_id id, bool continue_test )
bool was_in_progress = framework::test_in_progress();
bool call_start_finish = !continue_test || !was_in_progress;
-
- impl::s_frk_state().m_test_in_progress = true;
+ bool init_ok = true;
+ const_string setup_error;
if( call_start_finish ) {
+ // indicates the framework that no test is in progress now if observers need to be notified
+ impl::s_frk_state().m_test_in_progress = false;
+ // unit_test::framework_init_observer will get cleared first
BOOST_TEST_FOREACH( test_observer*, to, impl::s_frk_state().m_observers ) {
BOOST_TEST_I_TRY {
- impl::s_frk_state().m_aux_em.vexecute( boost::bind( &test_observer::test_start, to, tcc.p_count ) );
+ ut_detail::test_unit_id_restore restore_current_test_unit(impl::s_frk_state().m_curr_test_unit, id);
+ unit_test_monitor_t::error_level result = unit_test_monitor.execute_and_translate( boost::bind( &test_observer::test_start, to, tcc.p_count ) );
+ if( init_ok ) {
+ if( result != unit_test_monitor_t::test_ok ) {
+ init_ok = false;
+ }
+ else {
+ if( unit_test::framework_init_observer.has_failed() ) {
+ init_ok = false;
+ }
+ }
+ }
}
BOOST_TEST_I_CATCH( execution_exception, ex ) {
- BOOST_TEST_SETUP_ASSERT( false, ex.what() );
+ if( init_ok ) {
+ // log only the first error
+ init_ok = false;
+ setup_error = ex.what();
+ }
+ // break; // we should continue otherwise loggers may have improper structure (XML start missing for instance)
}
}
}
- unsigned seed = runtime_config::get<unsigned>( runtime_config::btrt_random_seed );
- switch( seed ) {
- case 0:
- break;
- case 1:
- seed = static_cast<unsigned>( std::rand() ^ std::time( 0 ) ); // better init using std::rand() ^ ...
- default:
- BOOST_TEST_FRAMEWORK_MESSAGE( "Test cases order is shuffled using seed: " << seed );
- std::srand( seed );
+ if( init_ok ) {
+
+ // attaching the global fixtures to the main entry point
+ test_unit& entry_test_unit = framework::get( id, TUT_ANY );
+ std::vector<test_unit_fixture_ptr> v_saved_fixture(entry_test_unit.p_fixtures.value.begin(),
+ entry_test_unit.p_fixtures.value.end());
+
+ BOOST_TEST_FOREACH( test_unit_fixture*, tuf, impl::s_frk_state().m_global_fixtures ) {
+ entry_test_unit.p_fixtures.value.insert( entry_test_unit.p_fixtures.value.begin(),
+ test_unit_fixture_ptr(new impl::global_fixture_handle(tuf)) );
+ }
+
+ swap_on_delete< std::vector<test_unit_fixture_ptr> > raii_fixture(v_saved_fixture, entry_test_unit.p_fixtures.value);
+
+ // now work in progress
+ impl::s_frk_state().m_test_in_progress = true;
+ unsigned seed = runtime_config::get<unsigned>( runtime_config::btrt_random_seed );
+ switch( seed ) {
+ case 0:
+ break;
+ case 1:
+ seed = static_cast<unsigned>( std::rand() ^ std::time( 0 ) ); // better init using std::rand() ^ ...
+ default:
+ BOOST_TEST_FRAMEWORK_MESSAGE( "Test cases order is shuffled using seed: " << seed );
+ std::srand( seed );
+ }
+
+ // executing the test tree
+ impl::s_frk_state().execute_test_tree( id );
+
+ // removing previously added global fixtures: dtor raii_fixture
}
- impl::s_frk_state().execute_test_tree( id );
+ impl::s_frk_state().m_test_in_progress = false;
+ unit_test::framework_init_observer.clear();
if( call_start_finish ) {
- BOOST_TEST_REVERSE_FOREACH( test_observer*, to, impl::s_frk_state().m_observers )
+ // indicates the framework that no test is in progress anymore if observers need to be notified
+ // and this is a teardown, so assertions should not raise any exception otherwise an exception
+ // might be raised in a dtor of a global fixture
+ impl::s_frk_state().m_test_in_progress = false;
+ BOOST_TEST_REVERSE_FOREACH( test_observer*, to, impl::s_frk_state().m_observers ) {
+ ut_detail::test_unit_id_restore restore_current_test_unit(impl::s_frk_state().m_curr_test_unit, id);
to->test_finish();
+ }
}
impl::s_frk_state().m_test_in_progress = was_in_progress;
+
+ // propagates the init/teardown error if any
+ BOOST_TEST_SETUP_ASSERT( init_ok && !unit_test::framework_init_observer.has_failed(), setup_error );
}
//____________________________________________________________________________//
@@ -1496,6 +1646,18 @@ test_unit_aborted( test_unit const& tu )
to->test_unit_aborted( tu );
}
+// ************************************************************************** //
+// ************** test_aborted ************** //
+// ************************************************************************** //
+
+void
+test_aborted( )
+{
+ BOOST_TEST_FOREACH( test_observer*, to, impl::s_frk_state().m_observers )
+ to->test_aborted( );
+}
+
+
//____________________________________________________________________________//
} // namespace framework
diff --git a/boost/test/impl/junit_log_formatter.ipp b/boost/test/impl/junit_log_formatter.ipp
index dd528bc903..0ec8d43832 100644
--- a/boost/test/impl/junit_log_formatter.ipp
+++ b/boost/test/impl/junit_log_formatter.ipp
@@ -69,6 +69,12 @@ inline std::string tu_name_normalize(std::string full_name)
return full_name;
}
+inline std::string tu_name_remove_newlines(std::string full_name)
+{
+ full_name.erase(std::remove(full_name.begin(), full_name.end(), '\n'), full_name.end());
+ return full_name;
+}
+
const_string file_basename(const_string filename) {
const_string path_sep( "\\/" );
@@ -86,7 +92,7 @@ const_string file_basename(const_string filename) {
// ************************************************************************** //
void
-junit_log_formatter::log_start( std::ostream& ostr, counter_t test_cases_amount)
+junit_log_formatter::log_start( std::ostream& /*ostr*/, counter_t /*test_cases_amount*/)
{
map_tests.clear();
list_path_to_root.clear();
@@ -96,6 +102,11 @@ junit_log_formatter::log_start( std::ostream& ostr, counter_t test_cases_amount)
//____________________________________________________________________________//
class junit_result_helper : public test_tree_visitor {
+private:
+ typedef junit_impl::junit_log_helper::assertion_entry assertion_entry;
+ typedef std::vector< assertion_entry >::const_iterator vect_assertion_entry_citerator;
+ typedef std::list<std::string>::const_iterator list_str_citerator;
+
public:
explicit junit_result_helper(
std::ostream& stream,
@@ -111,10 +122,19 @@ public:
, m_display_build_info(display_build_info)
{ }
- void add_log_entry(std::string const& entry_type,
- test_case const& tc,
- junit_impl::junit_log_helper::assertion_entry const& log) const
+ void add_log_entry(assertion_entry const& log) const
{
+ std::string entry_type;
+ if( log.log_entry == assertion_entry::log_entry_failure ) {
+ entry_type = "failure";
+ }
+ else if( log.log_entry == assertion_entry::log_entry_error ) {
+ entry_type = "error";
+ }
+ else {
+ return;
+ }
+
m_stream
<< "<" << entry_type
<< " message" << utils::attr_value() << log.logentry_message
@@ -159,24 +179,24 @@ public:
}
};
- std::list<std::string> build_skipping_chain(test_case const & tc) const
+ std::list<std::string> build_skipping_chain(test_unit const & tu) const
{
- // we enter here because we know that the tc has been skipped.
- // either junit has not seen this tc, or it is indicated as disabled
- assert(m_map_test.count(tc.p_id) == 0 || results_collector.results( tc.p_id ).p_skipped);
+ // we enter here because we know that the tu has been skipped.
+ // either junit has not seen this tu, or it is indicated as disabled
+ assert(m_map_test.count(tu.p_id) == 0 || results_collector.results( tu.p_id ).p_skipped);
std::list<std::string> out;
- test_unit_id id(tc.p_id);
+ test_unit_id id(tu.p_id);
while( id != m_ts.p_id && id != INV_TEST_UNIT_ID) {
- test_unit const& tu = boost::unit_test::framework::get( id, TUT_ANY );
- out.push_back("- disabled test unit: '" + tu.full_name() + "'\n");
+ test_unit const& tu_hierarchy = boost::unit_test::framework::get( id, TUT_ANY );
+ out.push_back("- disabled test unit: '" + tu_name_remove_newlines(tu_hierarchy.full_name()) + "'\n");
if(m_map_test.count(id) > 0)
{
// junit has seen the reason: this is enough for constructing the chain
break;
}
- id = tu.p_parent_id;
+ id = tu_hierarchy.p_parent_id;
}
junit_log_formatter::map_trace_t::const_iterator it_element_stack(m_map_test.find(id));
if( it_element_stack != m_map_test.end() )
@@ -188,9 +208,9 @@ public:
return out;
}
- std::string get_class_name(test_case const & tc) const {
+ std::string get_class_name(test_unit const & tu_class) const {
std::string classname;
- test_unit_id id(tc.p_parent_id);
+ test_unit_id id(tu_class.p_parent_id);
while( id != m_ts.p_id && id != INV_TEST_UNIT_ID ) {
test_unit const& tu = boost::unit_test::framework::get( id, TUT_ANY );
classname = tu_name_normalize(tu.p_name) + "." + classname;
@@ -205,39 +225,47 @@ public:
return classname;
}
- void write_testcase_header(test_case const & tc,
- test_results const *tr = 0) const
+ void write_testcase_header(test_unit const & tu,
+ test_results const *tr,
+ int nb_assertions) const
{
- //
- // test case header
+ std::string name;
+ std::string classname;
- // total number of assertions
- m_stream << "<testcase assertions" << utils::attr_value() << tr->p_assertions_passed + tr->p_assertions_failed;
+ if(tu.p_id == m_ts.p_id ) {
+ name = "boost_test";
+ }
+ else {
+ classname = get_class_name(tu);
+ name = tu_name_normalize(tu.p_name);
+ }
- // class name
- const std::string classname = get_class_name(tc);
+ if( tu.p_type == TUT_SUITE ) {
+ name += "-setup-teardown";
+ }
+
+ m_stream << "<testcase assertions" << utils::attr_value() << nb_assertions;
if(!classname.empty())
m_stream << " classname" << utils::attr_value() << classname;
// test case name and time taken
m_stream
- << " name" << utils::attr_value() << tu_name_normalize(tc.p_name)
+ << " name" << utils::attr_value() << name
<< " time" << utils::attr_value() << double(tr->p_duration_microseconds) * 1E-6
<< ">" << std::endl;
}
void write_testcase_system_out(junit_impl::junit_log_helper const &detailed_log,
- test_case const * tc,
- bool skipped,
- test_results const *tr = 0) const
+ test_unit const * tu,
+ bool skipped) const
{
// system-out + all info/messages, the object skips the empty entries
conditional_cdata_helper system_out_helper(m_stream, "system-out");
// indicate why the test has been skipped first
if( skipped ) {
- std::list<std::string> skipping_decision_chain = build_skipping_chain(*tc);
- for(std::list<std::string>::const_iterator it(skipping_decision_chain.begin()), ite(skipping_decision_chain.end());
+ std::list<std::string> skipping_decision_chain = build_skipping_chain(*tu);
+ for(list_str_citerator it(skipping_decision_chain.begin()), ite(skipping_decision_chain.end());
it != ite;
++it)
{
@@ -246,7 +274,7 @@ public:
}
// stdout
- for(std::list<std::string>::const_iterator it(detailed_log.system_out.begin()), ite(detailed_log.system_out.end());
+ for(list_str_citerator it(detailed_log.system_out.begin()), ite(detailed_log.system_out.end());
it != ite;
++it)
{
@@ -254,25 +282,24 @@ public:
}
// warning/info message last
- for(std::vector< junit_impl::junit_log_helper::assertion_entry >::const_iterator it(detailed_log.assertion_entries.begin());
+ for(vect_assertion_entry_citerator it(detailed_log.assertion_entries.begin());
it != detailed_log.assertion_entries.end();
++it)
{
- if(it->log_entry != junit_impl::junit_log_helper::assertion_entry::log_entry_info)
+ if(it->log_entry != assertion_entry::log_entry_info)
continue;
system_out_helper(it->output);
}
}
void write_testcase_system_err(junit_impl::junit_log_helper const &detailed_log,
- test_case const * tc,
- test_results const *tr = 0) const
+ test_unit const * tu,
+ test_results const *tr) const
{
// system-err output + test case informations
- bool has_failed = (tr != 0) ? !tr->passed() : false;
+ bool has_failed = (tr != 0) ? !tr->p_skipped && !tr->passed() : false;
if(!detailed_log.system_err.empty() || has_failed)
{
- conditional_cdata_helper system_err_helper(m_stream, "system-err");
std::ostringstream o;
if(has_failed) {
o << "Failures detected in:" << std::endl;
@@ -281,58 +308,89 @@ public:
o << "ERROR STREAM:" << std::endl;
}
- o << "- test case: " << tc->full_name() << std::endl;
- if(!tc->p_description.value.empty())
- o << " '" << tc->p_description << "'";
-
- o << std::endl
- << "- file: " << file_basename(tc->p_file_name) << std::endl
- << "- line: " << tc->p_line_num << std::endl
- ;
+ if(tu->p_type == TUT_SUITE) {
+ if( tu->p_id == m_ts.p_id ) {
+ o << " boost.test global setup/teardown" << std::endl;
+ } else {
+ o << "- test suite: " << tu_name_remove_newlines(tu->full_name()) << std::endl;
+ }
+ }
+ else {
+ o << "- test case: " << tu_name_remove_newlines(tu->full_name());
+ if(!tu->p_description.value.empty())
+ o << " '" << tu->p_description << "'";
+
+ o << std::endl
+ << "- file: " << file_basename(tu->p_file_name) << std::endl
+ << "- line: " << tu->p_line_num << std::endl
+ ;
+ }
if(!detailed_log.system_err.empty())
o << std::endl << "STDERR BEGIN: ------------" << std::endl;
- system_err_helper(o.str());
- for(std::list<std::string>::const_iterator it(detailed_log.system_err.begin()), ite(detailed_log.system_err.end());
+ for(list_str_citerator it(detailed_log.system_err.begin()), ite(detailed_log.system_err.end());
it != ite;
++it)
{
- system_err_helper(*it);
+ o << *it;
}
if(!detailed_log.system_err.empty())
o << std::endl << "STDERR END ------------" << std::endl;
+
+ conditional_cdata_helper system_err_helper(m_stream, "system-err");
+ system_err_helper(o.str());
+ }
+ }
+
+ int get_nb_assertions(junit_impl::junit_log_helper const &detailed_log,
+ test_unit const & tu,
+ test_results const *tr) const {
+ int nb_assertions(-1);
+ if( tu.p_type == TUT_SUITE ) {
+ nb_assertions = 0;
+ for(vect_assertion_entry_citerator it(detailed_log.assertion_entries.begin());
+ it != detailed_log.assertion_entries.end();
+ ++it)
+ {
+ if(it->log_entry != assertion_entry::log_entry_info)
+ nb_assertions++;
+ }
+ }
+ else {
+ nb_assertions = tr->p_assertions_passed + tr->p_assertions_failed;
}
+
+ return nb_assertions;
}
void output_detailed_logs(junit_impl::junit_log_helper const &detailed_log,
- test_case const & tc,
+ test_unit const & tu,
bool skipped,
- test_results const *tr = 0) const
+ test_results const *tr) const
{
- write_testcase_header(tc, tr);
+ int nb_assertions = get_nb_assertions(detailed_log, tu, tr);
+ if(!nb_assertions && tu.p_type == TUT_SUITE)
+ return;
+
+ write_testcase_header(tu, tr, nb_assertions);
if( skipped ) {
m_stream << "<skipped/>" << std::endl;
}
else {
- for(std::vector< junit_impl::junit_log_helper::assertion_entry >::const_iterator it(detailed_log.assertion_entries.begin());
+ for(vect_assertion_entry_citerator it(detailed_log.assertion_entries.begin());
it != detailed_log.assertion_entries.end();
++it)
{
- if(it->log_entry == junit_impl::junit_log_helper::assertion_entry::log_entry_failure) {
- add_log_entry("failure", tc, *it);
- }
- else if(it->log_entry == junit_impl::junit_log_helper::assertion_entry::log_entry_error) {
- add_log_entry("error", tc, *it);
- }
+ add_log_entry(*it);
}
}
- write_testcase_system_out(detailed_log, &tc, skipped, tr);
- write_testcase_system_err(detailed_log, &tc, tr);
+ write_testcase_system_out(detailed_log, &tu, skipped);
+ write_testcase_system_err(detailed_log, &tu, tr);
m_stream << "</testcase>" << std::endl;
}
@@ -353,35 +411,45 @@ public:
bool test_suite_start( test_suite const& ts )
{
- // unique test suite, without s, nesting not supported in CI
- if( m_ts.p_id != ts.p_id )
- return true;
-
test_results const& tr = results_collector.results( ts.p_id );
- m_stream << "<testsuite";
- m_stream
- // << "disabled=\"" << tr.p_test_cases_skipped << "\" "
- << " tests" << utils::attr_value() << tr.p_test_cases_passed
- << " skipped" << utils::attr_value() << tr.p_test_cases_skipped
- << " errors" << utils::attr_value() << tr.p_test_cases_aborted
- << " failures" << utils::attr_value() << tr.p_test_cases_failed
- << " id" << utils::attr_value() << m_id++
- << " name" << utils::attr_value() << tu_name_normalize(ts.p_name)
- << " time" << utils::attr_value() << (tr.p_duration_microseconds * 1E-6)
- << ">" << std::endl;
-
- if(m_display_build_info)
- {
- m_stream << "<properties>" << std::endl;
- m_stream << "<property name=\"platform\" value" << utils::attr_value() << BOOST_PLATFORM << std::endl;
- m_stream << "<property name=\"compiler\" value" << utils::attr_value() << BOOST_COMPILER << std::endl;
- m_stream << "<property name=\"stl\" value" << utils::attr_value() << BOOST_STDLIB << std::endl;
+ // unique test suite, without s, nesting not supported in CI
+ if( m_ts.p_id == ts.p_id ) {
+ m_stream << "<testsuite";
+
+ m_stream
+ // << "disabled=\"" << tr.p_test_cases_skipped << "\" "
+ << " tests" << utils::attr_value() << tr.p_test_cases_passed
+ << " skipped" << utils::attr_value() << tr.p_test_cases_skipped
+ << " errors" << utils::attr_value() << tr.p_test_cases_aborted
+ << " failures" << utils::attr_value() << tr.p_test_cases_failed
+ << " id" << utils::attr_value() << m_id++
+ << " name" << utils::attr_value() << tu_name_normalize(ts.p_name)
+ << " time" << utils::attr_value() << (tr.p_duration_microseconds * 1E-6)
+ << ">" << std::endl;
+
+ if(m_display_build_info)
+ {
+ m_stream << "<properties>" << std::endl;
+ m_stream << "<property name=\"platform\" value" << utils::attr_value() << BOOST_PLATFORM << std::endl;
+ m_stream << "<property name=\"compiler\" value" << utils::attr_value() << BOOST_COMPILER << std::endl;
+ m_stream << "<property name=\"stl\" value" << utils::attr_value() << BOOST_STDLIB << std::endl;
+
+ std::ostringstream o;
+ o << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100;
+ m_stream << "<property name=\"boost\" value" << utils::attr_value() << o.str() << std::endl;
+ m_stream << "</properties>" << std::endl;
+ }
+ }
- std::ostringstream o;
- o << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100;
- m_stream << "<property name=\"boost\" value" << utils::attr_value() << o.str() << std::endl;
- m_stream << "</properties>" << std::endl;
+ if( !tr.p_skipped ) {
+ // if we land here, then this is a chance that we are logging the fixture setup/teardown of a test-suite.
+ // the setup/teardown logging of a test-case is part of the test case.
+ // we do not care about the test-suite that were skipped (really??)
+ junit_log_formatter::map_trace_t::const_iterator it_find = m_map_test.find(ts.p_id);
+ if(it_find != m_map_test.end()) {
+ output_detailed_logs(it_find->second, ts, false, &tr);
+ }
}
return true; // indicates that the children should also be parsed
@@ -389,13 +457,13 @@ public:
virtual void test_suite_finish( test_suite const& ts )
{
- if( m_ts.p_id != ts.p_id )
- return;
+ if( m_ts.p_id == ts.p_id ) {
+ write_testcase_system_out(runner_log, 0, false);
+ write_testcase_system_err(runner_log, 0, 0);
- write_testcase_system_out(runner_log, 0, false, 0);
- write_testcase_system_err(runner_log, 0, 0);
-
- m_stream << "</testsuite>";
+ m_stream << "</testsuite>";
+ return;
+ }
}
private:
@@ -439,7 +507,7 @@ junit_log_formatter::log_finish( std::ostream& ostr )
//____________________________________________________________________________//
void
-junit_log_formatter::log_build_info( std::ostream& ostr )
+junit_log_formatter::log_build_info( std::ostream& /*ostr*/ )
{
m_display_build_info = true;
}
@@ -447,7 +515,7 @@ junit_log_formatter::log_build_info( std::ostream& ostr )
//____________________________________________________________________________//
void
-junit_log_formatter::test_unit_start( std::ostream& ostr, test_unit const& tu )
+junit_log_formatter::test_unit_start( std::ostream& /*ostr*/, test_unit const& tu )
{
list_path_to_root.push_back( tu.p_id );
map_tests.insert(std::make_pair(tu.p_id, junit_impl::junit_log_helper())); // current_test_case_id not working here
@@ -458,7 +526,7 @@ junit_log_formatter::test_unit_start( std::ostream& ostr, test_unit const& tu )
//____________________________________________________________________________//
void
-junit_log_formatter::test_unit_finish( std::ostream& ostr, test_unit const& tu, unsigned long elapsed )
+junit_log_formatter::test_unit_finish( std::ostream& /*ostr*/, test_unit const& tu, unsigned long /*elapsed*/ )
{
// the time is already stored in the result_reporter
assert( tu.p_id == list_path_to_root.back() );
@@ -466,7 +534,7 @@ junit_log_formatter::test_unit_finish( std::ostream& ostr, test_unit const& tu,
}
void
-junit_log_formatter::test_unit_aborted( std::ostream& os, test_unit const& tu )
+junit_log_formatter::test_unit_aborted( std::ostream& /*ostr*/, test_unit const& tu )
{
assert( tu.p_id == list_path_to_root.back() );
//list_path_to_root.pop_back();
@@ -475,7 +543,7 @@ junit_log_formatter::test_unit_aborted( std::ostream& os, test_unit const& tu )
//____________________________________________________________________________//
void
-junit_log_formatter::test_unit_skipped( std::ostream& ostr, test_unit const& tu, const_string reason )
+junit_log_formatter::test_unit_skipped( std::ostream& /*ostr*/, test_unit const& tu, const_string reason )
{
// if a test unit is skipped, then the start of this TU has not been called yet.
// we cannot use get_current_log_entry here, but the TU id should appear in the map.
@@ -487,7 +555,7 @@ junit_log_formatter::test_unit_skipped( std::ostream& ostr, test_unit const& tu,
//____________________________________________________________________________//
void
-junit_log_formatter::log_exception_start( std::ostream& ostr, log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
+junit_log_formatter::log_exception_start( std::ostream& /*ostr*/, log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
{
std::ostringstream o;
execution_exception::location const& loc = ex.where();
@@ -555,7 +623,7 @@ junit_log_formatter::log_exception_start( std::ostream& ostr, log_checkpoint_dat
//____________________________________________________________________________//
void
-junit_log_formatter::log_exception_finish( std::ostream& ostr )
+junit_log_formatter::log_exception_finish( std::ostream& /*ostr*/ )
{
// sealing the last entry
assert(!get_current_log_entry().assertion_entries.back().sealed);
@@ -565,7 +633,7 @@ junit_log_formatter::log_exception_finish( std::ostream& ostr )
//____________________________________________________________________________//
void
-junit_log_formatter::log_entry_start( std::ostream& ostr, log_entry_data const& entry_data, log_entry_types let )
+junit_log_formatter::log_entry_start( std::ostream& /*ostr*/, log_entry_data const& entry_data, log_entry_types let )
{
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
last_entry.skipping = false;
@@ -638,7 +706,7 @@ junit_log_formatter::log_entry_start( std::ostream& ostr, log_entry_data const&
//____________________________________________________________________________//
void
-junit_log_formatter::log_entry_value( std::ostream& ostr, const_string value )
+junit_log_formatter::log_entry_value( std::ostream& /*ostr*/, const_string value )
{
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
if(last_entry.skipping)
@@ -662,7 +730,7 @@ junit_log_formatter::log_entry_value( std::ostream& ostr, const_string value )
//____________________________________________________________________________//
void
-junit_log_formatter::log_entry_finish( std::ostream& ostr )
+junit_log_formatter::log_entry_finish( std::ostream& /*ostr*/ )
{
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
if(!last_entry.skipping)
@@ -685,7 +753,7 @@ junit_log_formatter::log_entry_finish( std::ostream& ostr )
//____________________________________________________________________________//
void
-junit_log_formatter::entry_context_start( std::ostream& ostr, log_level )
+junit_log_formatter::entry_context_start( std::ostream& /*ostr*/, log_level )
{
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
if(last_entry.skipping)
@@ -708,7 +776,7 @@ junit_log_formatter::entry_context_start( std::ostream& ostr, log_level )
//____________________________________________________________________________//
void
-junit_log_formatter::entry_context_finish( std::ostream& ostr )
+junit_log_formatter::entry_context_finish( std::ostream& /*ostr*/, log_level )
{
// no op, may be removed
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
@@ -720,7 +788,7 @@ junit_log_formatter::entry_context_finish( std::ostream& ostr )
//____________________________________________________________________________//
void
-junit_log_formatter::log_entry_context( std::ostream& ostr, const_string context_descr )
+junit_log_formatter::log_entry_context( std::ostream& /*ostr*/, log_level , const_string context_descr )
{
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
if(last_entry.skipping)
diff --git a/boost/test/impl/results_collector.ipp b/boost/test/impl/results_collector.ipp
index daee8bc3bf..fd74bdb65c 100644
--- a/boost/test/impl/results_collector.ipp
+++ b/boost/test/impl/results_collector.ipp
@@ -59,6 +59,12 @@ test_results::passed() const
!p_aborted;
}
+bool
+test_results::aborted() const
+{
+ return p_aborted;
+}
+
//____________________________________________________________________________//
int
diff --git a/boost/test/impl/test_framework_init_observer.ipp b/boost/test/impl/test_framework_init_observer.ipp
new file mode 100644
index 0000000000..89f854aaed
--- /dev/null
+++ b/boost/test/impl/test_framework_init_observer.ipp
@@ -0,0 +1,109 @@
+// (c) Copyright Raffi Enficiaud 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/test for the library home page.
+//
+//! @file
+//! An observer for monitoring the success/failure of the other observers
+// ***************************************************************************
+
+#ifndef BOOST_TEST_FRAMEWORK_INIT_OBSERVER_IPP_021105GER
+#define BOOST_TEST_FRAMEWORK_INIT_OBSERVER_IPP_021105GER
+
+// Boost.Test
+#include <boost/test/test_framework_init_observer.hpp>
+#include <boost/test/framework.hpp>
+#include <boost/test/detail/suppress_warnings.hpp>
+
+//____________________________________________________________________________//
+
+namespace boost {
+namespace unit_test {
+
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** framework_init_observer_t ************** //
+// ************************************************************************** //
+
+namespace {
+
+struct test_init_observer_check {
+ bool has_failure;
+
+ void clear()
+ {
+ has_failure = false;
+ }
+};
+
+
+test_init_observer_check& s_tioc_impl() { static test_init_observer_check the_inst; return the_inst; }
+
+} // local namespace
+
+void
+framework_init_observer_t::clear()
+{
+ if(!framework::test_in_progress())
+ s_tioc_impl().clear();
+}
+
+//____________________________________________________________________________//
+
+void
+framework_init_observer_t::test_start( counter_t )
+{
+ clear();
+}
+
+//____________________________________________________________________________//
+
+void
+framework_init_observer_t::assertion_result( unit_test::assertion_result ar )
+{
+ test_init_observer_check& tr = s_tioc_impl();
+ switch( ar ) {
+ case AR_TRIGGERED: break;
+ case AR_PASSED: break;
+ case AR_FAILED: tr.has_failure = true; break;
+ default:
+ break;
+ }
+}
+
+//____________________________________________________________________________//
+
+void
+framework_init_observer_t::exception_caught( execution_exception const& )
+{
+ test_init_observer_check& tr = s_tioc_impl();
+ tr.has_failure = true;
+}
+
+void
+framework_init_observer_t::test_aborted()
+{
+ s_tioc_impl().has_failure = true;
+}
+
+
+//____________________________________________________________________________//
+
+bool
+framework_init_observer_t::has_failed() const
+{
+ return s_tioc_impl().has_failure;
+}
+
+//____________________________________________________________________________//
+
+} // namespace unit_test
+} // namespace boost
+
+#include <boost/test/detail/enable_warnings.hpp>
+
+#endif // BOOST_TEST_FRAMEWORK_INIT_OBSERVER_IPP_021105GER
diff --git a/boost/test/impl/test_tools.ipp b/boost/test/impl/test_tools.ipp
index 853b3913ee..7e01453313 100644
--- a/boost/test/impl/test_tools.ipp
+++ b/boost/test/impl/test_tools.ipp
@@ -121,7 +121,7 @@ print_log_value<wchar_t const*>::operator()( std::ostream& ostr, wchar_t const*
#if !defined(BOOST_NO_CXX11_NULLPTR)
void
-print_log_value<std::nullptr_t>::operator()( std::ostream& ostr, std::nullptr_t p )
+print_log_value<std::nullptr_t>::operator()( std::ostream& ostr, std::nullptr_t )
{
ostr << "nullptr";
}
@@ -310,8 +310,19 @@ report_assertion( assertion_result const& ar,
{
using namespace unit_test;
- BOOST_TEST_I_ASSRT( framework::current_test_case_id() != INV_TEST_UNIT_ID,
- std::runtime_error( "Can't use testing tools outside of test case implementation." ) );
+ if( !framework::test_in_progress() ) {
+ // in case no test is in progress, we do not throw anything:
+ // raising an exception here may result in raising an exception in a destructor of a global fixture
+ // which will abort the process
+ // We flag this as aborted instead
+
+ //BOOST_TEST_I_ASSRT( framework::current_test_case_id() != INV_TEST_UNIT_ID,
+ // std::runtime_error( "Can't use testing tools outside of test case implementation." ) );
+
+ framework::test_aborted();
+ return false;
+ }
+
if( !!ar )
tl = PASS;
@@ -369,10 +380,9 @@ report_assertion( assertion_result const& ar,
case REQUIRE:
framework::assertion_result( AR_FAILED );
-
- framework::test_unit_aborted( framework::current_test_case() );
-
+ framework::test_unit_aborted( framework::current_test_unit() );
BOOST_TEST_I_THROW( execution_aborted() );
+ return false;
}
return true;
@@ -493,7 +503,7 @@ struct output_test_stream::Impl
char get_char()
{
- char res;
+ char res = 0;
do {
m_pattern.get( res );
} while( m_text_or_binary && res == '\r' && !m_pattern.fail() && !m_pattern.eof() );
@@ -619,6 +629,7 @@ output_test_stream::match_pattern( bool flush_stream )
int offset = 0;
std::vector<char> last_elements;
for ( std::string::size_type i = 0; static_cast<int>(i + offset) < static_cast<int>(stream_string_repr.length()); ++i ) {
+
char c = m_pimpl->get_char();
if( last_elements.size() <= n_chars_presuffix ) {
@@ -698,7 +709,7 @@ output_test_stream::match_pattern( bool flush_stream )
if( last_elements_ordered[pattern_start_index + k] == sub_str_suffix[stream_start_index + k] )
nb_char_in_common ++;
else
- break; // we take fully macthing substring only
+ break; // we take fully matching substring only
}
if( nb_char_in_common > max_nb_char_in_common ) {
@@ -709,20 +720,32 @@ output_test_stream::match_pattern( bool flush_stream )
}
}
- // indicates with more precision the location of the mismatchs in ascii arts ...
+ // indicates with more precision the location of the mismatchs in "ascii arts" ...
result.message() << " ...\n... ";
for( std::string::size_type j = 0; j < sub_str_prefix.size(); j++) {
result.message() << ' ';
}
- for( std::size_t k = 0; k < (std::max)(best_pattern_start_index, best_stream_start_index); k++ ) { // 1 is for the current char c
+ result.message() << '~'; // places the first tilde at the current char that mismatches
+
+ for( std::size_t k = 1; k < (std::max)(best_pattern_start_index, best_stream_start_index); k++ ) { // 1 is for the current char c
std::string s1(pretty_print_log(std::string(1, last_elements_ordered[(std::min)(k, best_pattern_start_index)])));
std::string s2(pretty_print_log(std::string(1, sub_str_suffix[(std::min)(k, best_stream_start_index)])));
for( int h = (std::max)(s1.size(), s2.size()); h > 0; h--)
- result.message() << "~";
+ result.message() << "~";
+ }
+
+ if( m_pimpl->m_pattern.eof() ) {
+ result.message() << " (reference string shorter than current stream)";
}
+
result.message() << "\n";
+ // no need to continue if the EOF is reached
+ if( m_pimpl->m_pattern.eof() ) {
+ break;
+ }
+
// first char is a replicat of c, so we do not copy it.
for(std::string::size_type counter = 0; counter < last_elements_ordered.size() - 1 ; counter++)
last_elements[ (i + 1 + counter) % last_elements.size() ] = last_elements_ordered[counter + 1];
diff --git a/boost/test/impl/test_tree.ipp b/boost/test/impl/test_tree.ipp
index 08bdad3360..81995bb29f 100644
--- a/boost/test/impl/test_tree.ipp
+++ b/boost/test/impl/test_tree.ipp
@@ -448,9 +448,28 @@ auto_test_unit_registrar::auto_test_unit_registrar( int )
global_fixture::global_fixture()
{
+ framework::register_global_fixture( *this );
+}
+
+global_fixture::~global_fixture()
+{
+ framework::deregister_global_fixture( *this );
+}
+
+// ************************************************************************** //
+// ************** global_configuration ************** //
+// ************************************************************************** //
+
+global_configuration::global_configuration()
+{
framework::register_observer( *this );
}
+global_configuration::~global_configuration()
+{
+ framework::deregister_observer( *this );
+}
+
//____________________________________________________________________________//
} // namespace unit_test
diff --git a/boost/test/impl/unit_test_log.ipp b/boost/test/impl/unit_test_log.ipp
index c52260b94b..6ef7d930a2 100644
--- a/boost/test/impl/unit_test_log.ipp
+++ b/boost/test/impl/unit_test_log.ipp
@@ -171,6 +171,8 @@ unit_test_log_t::test_start( counter_t test_cases_amount )
if( runtime_config::get<bool>( runtime_config::btrt_build_info ) )
current_logger_data.m_log_formatter->log_build_info( current_logger_data.stream() );
+ //current_logger_data.stream().flush();
+
current_logger_data.m_entry_in_progress = false;
}
}
@@ -472,14 +474,14 @@ unit_test_log_t::log_entry_context( log_level l )
{
BOOST_TEST_FOREACH( unit_test_log_data_helper_impl&, current_logger_data, s_log_impl().m_log_formatter_data ) {
if( current_logger_data.m_enabled ) {
- current_logger_data.m_log_formatter->log_entry_context( current_logger_data.stream(), frame );
+ current_logger_data.m_log_formatter->log_entry_context( current_logger_data.stream(), l, frame );
}
}
}
BOOST_TEST_FOREACH( unit_test_log_data_helper_impl&, current_logger_data, s_log_impl().m_log_formatter_data ) {
if( current_logger_data.m_enabled ) {
- current_logger_data.m_log_formatter->entry_context_finish( current_logger_data.stream() );
+ current_logger_data.m_log_formatter->entry_context_finish( current_logger_data.stream(), l );
}
}
}
diff --git a/boost/test/impl/unit_test_monitor.ipp b/boost/test/impl/unit_test_monitor.ipp
index fdd36f7c3a..cfb41a239c 100644
--- a/boost/test/impl/unit_test_monitor.ipp
+++ b/boost/test/impl/unit_test_monitor.ipp
@@ -47,7 +47,7 @@ unit_test_monitor_t::execute_and_translate( boost::function<void ()> const& func
}
BOOST_TEST_I_CATCH( execution_exception, ex ) {
framework::exception_caught( ex );
- framework::test_unit_aborted( framework::current_test_case() );
+ framework::test_unit_aborted( framework::current_test_unit() );
// translate execution_exception::error_code to error_level
switch( ex.code() ) {
diff --git a/boost/test/impl/xml_log_formatter.ipp b/boost/test/impl/xml_log_formatter.ipp
index 81284020dd..ef44f1eade 100644
--- a/boost/test/impl/xml_log_formatter.ipp
+++ b/boost/test/impl/xml_log_formatter.ipp
@@ -199,7 +199,7 @@ xml_log_formatter::entry_context_start( std::ostream& ostr, log_level )
//____________________________________________________________________________//
void
-xml_log_formatter::entry_context_finish( std::ostream& ostr )
+xml_log_formatter::entry_context_finish( std::ostream& ostr, log_level )
{
ostr << BOOST_TEST_L( "</Context>" );
}
@@ -207,7 +207,7 @@ xml_log_formatter::entry_context_finish( std::ostream& ostr )
//____________________________________________________________________________//
void
-xml_log_formatter::log_entry_context( std::ostream& ostr, const_string context_descr )
+xml_log_formatter::log_entry_context( std::ostream& ostr, log_level, const_string context_descr )
{
ostr << BOOST_TEST_L( "<Frame>" ) << utils::cdata() << context_descr << BOOST_TEST_L( "</Frame>" );
}
diff --git a/boost/test/included/test_exec_monitor.hpp b/boost/test/included/test_exec_monitor.hpp
index 34b6ef44dd..e75b4698f2 100644
--- a/boost/test/included/test_exec_monitor.hpp
+++ b/boost/test/included/test_exec_monitor.hpp
@@ -23,6 +23,7 @@
#include <boost/test/impl/progress_monitor.ipp>
#include <boost/test/impl/results_collector.ipp>
#include <boost/test/impl/results_reporter.ipp>
+#include <boost/test/impl/test_framework_init_observer.ipp>
#include <boost/test/impl/test_main.ipp>
#include <boost/test/impl/test_tools.ipp>
#include <boost/test/impl/test_tree.ipp>
diff --git a/boost/test/included/unit_test.hpp b/boost/test/included/unit_test.hpp
index 993d75e4c0..90882eb178 100644
--- a/boost/test/included/unit_test.hpp
+++ b/boost/test/included/unit_test.hpp
@@ -5,6 +5,7 @@
// See http://www.boost.org/libs/test for the library home page.
//
+//
//!@file
//!@brief Included (vs. linked) version of Unit Test Framework
// ***************************************************************************
@@ -24,6 +25,7 @@
#include <boost/test/impl/progress_monitor.ipp>
#include <boost/test/impl/results_collector.ipp>
#include <boost/test/impl/results_reporter.ipp>
+#include <boost/test/impl/test_framework_init_observer.ipp>
#include <boost/test/impl/test_tools.ipp>
#include <boost/test/impl/test_tree.ipp>
#include <boost/test/impl/unit_test_log.ipp>
@@ -31,7 +33,6 @@
#include <boost/test/impl/unit_test_monitor.ipp>
#include <boost/test/impl/unit_test_parameters.ipp>
#include <boost/test/impl/xml_log_formatter.ipp>
-#include <boost/test/impl/junit_log_formatter.ipp>
#include <boost/test/impl/xml_report_formatter.ipp>
#include <boost/test/unit_test.hpp>
diff --git a/boost/test/output/compiler_log_formatter.hpp b/boost/test/output/compiler_log_formatter.hpp
index cb6172aab6..50359334b1 100644
--- a/boost/test/output/compiler_log_formatter.hpp
+++ b/boost/test/output/compiler_log_formatter.hpp
@@ -51,8 +51,8 @@ public:
void log_entry_finish( std::ostream& );
void entry_context_start( std::ostream&, log_level );
- void log_entry_context( std::ostream&, const_string );
- void entry_context_finish( std::ostream& );
+ void log_entry_context( std::ostream&, log_level l, const_string );
+ void entry_context_finish( std::ostream&, log_level l );
protected:
virtual void print_prefix( std::ostream&, const_string file, std::size_t line );
diff --git a/boost/test/output/junit_log_formatter.hpp b/boost/test/output/junit_log_formatter.hpp
index 325a1d8a17..713d3b016c 100644
--- a/boost/test/output/junit_log_formatter.hpp
+++ b/boost/test/output/junit_log_formatter.hpp
@@ -118,8 +118,8 @@ public:
void log_entry_finish( std::ostream& );
void entry_context_start( std::ostream&, log_level );
- void log_entry_context( std::ostream&, const_string );
- void entry_context_finish( std::ostream& );
+ void log_entry_context( std::ostream&, log_level, const_string );
+ void entry_context_finish( std::ostream&, log_level );
//! Discards changes in the log level
virtual void set_log_level(log_level ll)
diff --git a/boost/test/output/xml_log_formatter.hpp b/boost/test/output/xml_log_formatter.hpp
index 4d848a0425..1d8dec0f95 100644
--- a/boost/test/output/xml_log_formatter.hpp
+++ b/boost/test/output/xml_log_formatter.hpp
@@ -54,8 +54,8 @@ public:
void log_entry_finish( std::ostream& );
void entry_context_start( std::ostream&, log_level );
- void log_entry_context( std::ostream&, const_string );
- void entry_context_finish( std::ostream& );
+ void log_entry_context( std::ostream&, log_level, const_string );
+ void entry_context_finish( std::ostream&, log_level );
private:
// Data members
diff --git a/boost/test/progress_monitor.hpp b/boost/test/progress_monitor.hpp
index e480ac669d..2f661f5825 100644
--- a/boost/test/progress_monitor.hpp
+++ b/boost/test/progress_monitor.hpp
@@ -41,7 +41,7 @@ public:
virtual void test_unit_finish( test_unit const&, unsigned long );
virtual void test_unit_skipped( test_unit const&, const_string );
- virtual int priority() { return 3; }
+ virtual int priority() { return 4; }
/// @}
/// @name Configuration
diff --git a/boost/test/results_collector.hpp b/boost/test/results_collector.hpp
index 7d2c2bee58..3acd7b87bc 100644
--- a/boost/test/results_collector.hpp
+++ b/boost/test/results_collector.hpp
@@ -79,6 +79,9 @@ public:
/// Returns true if test unit passed
bool passed() const;
+ /// Returns true if the test unit was aborted (hard failure)
+ bool aborted() const;
+
/// Produces result code for the test unit execution
///
/// This methhod return one of the result codes defined in @c boost/cstdlib.hpp
@@ -119,7 +122,7 @@ public:
virtual void assertion_result( unit_test::assertion_result );
virtual void exception_caught( execution_exception const& );
- virtual int priority() { return 2; }
+ virtual int priority() { return 3; }
/// Results access per test unit
///
diff --git a/boost/test/test_framework_init_observer.hpp b/boost/test/test_framework_init_observer.hpp
new file mode 100644
index 0000000000..cdf5ef5edd
--- /dev/null
+++ b/boost/test/test_framework_init_observer.hpp
@@ -0,0 +1,63 @@
+// (c) Copyright Raffi Enficiaud 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/test for the library home page.
+//
+/// @file
+/// @brief Defines an observer that monitors the init of the unit test framework
+// ***************************************************************************
+
+#ifndef BOOST_TEST_FRAMEWORK_INIT_OBSERVER_HPP_071894GER
+#define BOOST_TEST_FRAMEWORK_INIT_OBSERVER_HPP_071894GER
+
+// Boost.Test
+#include <boost/test/tree/observer.hpp>
+
+#include <boost/test/detail/global_typedef.hpp>
+#include <boost/test/detail/fwd_decl.hpp>
+
+#include <boost/test/utils/trivial_singleton.hpp>
+
+#include <boost/test/detail/suppress_warnings.hpp>
+
+//____________________________________________________________________________//
+
+namespace boost {
+namespace unit_test {
+
+// ************************************************************************** //
+/// @brief Monitors the init of the framework
+///
+/// This class collects the state of the init/termination of the unit test framework.
+///
+/// @see boost::unit_test::test_observer
+class BOOST_TEST_DECL framework_init_observer_t : public test_observer, public singleton<framework_init_observer_t> {
+public:
+
+ virtual void test_start( counter_t );
+
+ virtual void assertion_result( unit_test::assertion_result );
+ virtual void exception_caught( execution_exception const& );
+ virtual void test_aborted();
+
+ virtual int priority() { return 0; }
+
+ void clear();
+
+ /// Indicates if a failure has been recorded so far
+ bool has_failed( ) const;
+
+private:
+ BOOST_TEST_SINGLETON_CONS( framework_init_observer_t )
+};
+
+BOOST_TEST_SINGLETON_INST( framework_init_observer )
+
+} // namespace unit_test
+} // namespace boost
+
+#include <boost/test/detail/enable_warnings.hpp>
+
+#endif // BOOST_TEST_FRAMEWORK_INIT_OBSERVER_HPP_071894GER
diff --git a/boost/test/tools/collection_comparison_op.hpp b/boost/test/tools/collection_comparison_op.hpp
index 396de502f8..864103fb4a 100644
--- a/boost/test/tools/collection_comparison_op.hpp
+++ b/boost/test/tools/collection_comparison_op.hpp
@@ -38,6 +38,15 @@ namespace assertion {
template<typename T>
struct specialized_compare : public mpl::false_ {};
+template <typename T>
+struct is_c_array : public mpl::false_ {};
+
+template<typename T, std::size_t N>
+struct is_c_array<T [N]> : public mpl::true_ {};
+
+template<typename T, std::size_t N>
+struct is_c_array<T (&)[N]> : public mpl::true_ {};
+
#define BOOST_TEST_SPECIALIZED_COLLECTION_COMPARE(Col) \
namespace boost { namespace test_tools { namespace assertion { \
template<> \
@@ -55,17 +64,21 @@ template <typename OP, bool can_be_equal, bool prefer_shorter,
typename Lhs, typename Rhs>
inline
typename boost::enable_if_c<
- unit_test::is_forward_iterable<Lhs>::value && unit_test::is_forward_iterable<Rhs>::value,
+ unit_test::is_forward_iterable<Lhs>::value && !unit_test::is_cstring<Lhs>::value
+ && unit_test::is_forward_iterable<Rhs>::value && !unit_test::is_cstring<Rhs>::value,
assertion_result>::type
lexicographic_compare( Lhs const& lhs, Rhs const& rhs )
{
assertion_result ar( true );
- typename Lhs::const_iterator first1 = lhs.begin();
- typename Rhs::const_iterator first2 = rhs.begin();
- typename Lhs::const_iterator last1 = lhs.end();
- typename Rhs::const_iterator last2 = rhs.end();
- std::size_t pos = 0;
+ typedef unit_test::bt_iterator_traits<Lhs> t_Lhs_iterator;
+ typedef unit_test::bt_iterator_traits<Rhs> t_Rhs_iterator;
+
+ typename t_Lhs_iterator::const_iterator first1 = t_Lhs_iterator::begin(lhs);
+ typename t_Rhs_iterator::const_iterator first2 = t_Rhs_iterator::begin(rhs);
+ typename t_Lhs_iterator::const_iterator last1 = t_Lhs_iterator::end(lhs);
+ typename t_Rhs_iterator::const_iterator last2 = t_Rhs_iterator::end(rhs);
+ std::size_t pos = 0;
for( ; (first1 != last1) && (first2 != last2); ++first1, ++first2, ++pos ) {
assertion_result const& element_ar = OP::eval(*first1, *first2);
@@ -113,8 +126,7 @@ template <typename OP, bool can_be_equal, bool prefer_shorter,
typename Lhs, typename Rhs>
inline
typename boost::enable_if_c<
- (!unit_test::is_forward_iterable<Lhs>::value && unit_test::is_cstring<Lhs>::value) ||
- (!unit_test::is_forward_iterable<Rhs>::value && unit_test::is_cstring<Rhs>::value),
+ (unit_test::is_cstring<Lhs>::value || unit_test::is_cstring<Rhs>::value),
assertion_result>::type
lexicographic_compare( Lhs const& lhs, Rhs const& rhs )
{
@@ -122,8 +134,8 @@ lexicographic_compare( Lhs const& lhs, Rhs const& rhs )
typedef typename unit_test::deduce_cstring<Rhs>::type rhs_char_type;
return lexicographic_compare<OP, can_be_equal, prefer_shorter>(
- boost::unit_test::basic_cstring<lhs_char_type>(lhs),
- boost::unit_test::basic_cstring<rhs_char_type>(rhs));
+ lhs_char_type(lhs),
+ rhs_char_type(rhs));
}
//____________________________________________________________________________//
@@ -135,23 +147,27 @@ lexicographic_compare( Lhs const& lhs, Rhs const& rhs )
template <typename OP, typename Lhs, typename Rhs>
inline
typename boost::enable_if_c<
- unit_test::is_forward_iterable<Lhs>::value && unit_test::is_forward_iterable<Rhs>::value,
+ unit_test::is_forward_iterable<Lhs>::value && !unit_test::is_cstring<Lhs>::value
+ && unit_test::is_forward_iterable<Rhs>::value && !unit_test::is_cstring<Rhs>::value,
assertion_result>::type
element_compare( Lhs const& lhs, Rhs const& rhs )
{
+ typedef unit_test::bt_iterator_traits<Lhs> t_Lhs_iterator;
+ typedef unit_test::bt_iterator_traits<Rhs> t_Rhs_iterator;
+
assertion_result ar( true );
- if( lhs.size() != rhs.size() ) {
+ if( t_Lhs_iterator::size(lhs) != t_Rhs_iterator::size(rhs) ) {
ar = false;
- ar.message() << "\nCollections size mismatch: " << lhs.size() << " != " << rhs.size();
+ ar.message() << "\nCollections size mismatch: " << t_Lhs_iterator::size(lhs) << " != " << t_Rhs_iterator::size(rhs);
return ar;
}
- typename Lhs::const_iterator left = lhs.begin();
- typename Rhs::const_iterator right = rhs.begin();
- std::size_t pos = 0;
+ typename t_Lhs_iterator::const_iterator left = t_Lhs_iterator::begin(lhs);
+ typename t_Rhs_iterator::const_iterator right = t_Rhs_iterator::begin(rhs);
+ std::size_t pos = 0;
- for( ; pos < lhs.size(); ++left, ++right, ++pos ) {
+ for( ; pos < t_Lhs_iterator::size(lhs); ++left, ++right, ++pos ) {
assertion_result const element_ar = OP::eval( *left, *right );
if( element_ar )
continue;
@@ -171,16 +187,15 @@ element_compare( Lhs const& lhs, Rhs const& rhs )
template <typename OP, typename Lhs, typename Rhs>
inline
typename boost::enable_if_c<
- (!unit_test::is_forward_iterable<Lhs>::value && unit_test::is_cstring<Lhs>::value) ||
- (!unit_test::is_forward_iterable<Rhs>::value && unit_test::is_cstring<Rhs>::value),
+ (unit_test::is_cstring<Lhs>::value || unit_test::is_cstring<Rhs>::value),
assertion_result>::type
element_compare( Lhs const& lhs, Rhs const& rhs )
{
typedef typename unit_test::deduce_cstring<Lhs>::type lhs_char_type;
typedef typename unit_test::deduce_cstring<Rhs>::type rhs_char_type;
- return element_compare<OP>(boost::unit_test::basic_cstring<lhs_char_type>(lhs),
- boost::unit_test::basic_cstring<rhs_char_type>(rhs));
+ return element_compare<OP>(lhs_char_type(lhs),
+ rhs_char_type(rhs));
}
//____________________________________________________________________________//
@@ -193,14 +208,17 @@ template <typename OP, typename Lhs, typename Rhs>
inline assertion_result
non_equality_compare( Lhs const& lhs, Rhs const& rhs )
{
+ typedef unit_test::bt_iterator_traits<Lhs> t_Lhs_iterator;
+ typedef unit_test::bt_iterator_traits<Rhs> t_Rhs_iterator;
+
assertion_result ar( true );
- if( lhs.size() != rhs.size() )
+ if( t_Lhs_iterator::size(lhs) != t_Rhs_iterator::size(rhs) )
return ar;
- typename Lhs::const_iterator left = lhs.begin();
- typename Rhs::const_iterator right = rhs.begin();
- typename Lhs::const_iterator end = lhs.end();
+ typename t_Lhs_iterator::const_iterator left = t_Lhs_iterator::begin(lhs);
+ typename t_Rhs_iterator::const_iterator right = t_Rhs_iterator::begin(rhs);
+ typename t_Lhs_iterator::const_iterator end = t_Lhs_iterator::end(lhs);
for( ; left != end; ++left, ++right ) {
if( OP::eval( *left, *right ) )
@@ -367,22 +385,34 @@ compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::GE<L, R> >*
#define DEFINE_COLLECTION_COMPARISON( oper, name, rev ) \
template<typename Lhs,typename Rhs> \
struct name<Lhs,Rhs,typename boost::enable_if_c< \
- unit_test::is_forward_iterable<Lhs>::value \
- && !unit_test::is_cstring<Lhs>::value \
- && unit_test::is_forward_iterable<Rhs>::value \
- && !unit_test::is_cstring<Rhs>::value>::type> { \
+ unit_test::is_forward_iterable<Lhs>::value \
+ && !unit_test::is_cstring_comparable<Lhs>::value \
+ && unit_test::is_forward_iterable<Rhs>::value \
+ && !unit_test::is_cstring_comparable<Rhs>::value>::type> { \
public: \
typedef assertion_result result_type; \
+ typedef unit_test::bt_iterator_traits<Lhs> t_Lhs_iterator_helper; \
+ typedef unit_test::bt_iterator_traits<Rhs> t_Rhs_iterator_helper; \
\
typedef name<Lhs, Rhs> OP; \
+ \
typedef typename \
- mpl::if_c<is_same<typename decay<Lhs>::type, \
- typename decay<Rhs>::type>::value, \
- typename cctraits<OP>::is_specialized, \
- mpl::false_>::type is_specialized; \
+ mpl::if_c< \
+ mpl::or_< \
+ typename is_c_array<Lhs>::type, \
+ typename is_c_array<Rhs>::type \
+ >::value, \
+ mpl::true_, \
+ typename \
+ mpl::if_c<is_same<typename decay<Lhs>::type, \
+ typename decay<Rhs>::type>::value, \
+ typename cctraits<OP>::is_specialized, \
+ mpl::false_>::type \
+ >::type is_specialized; \
\
- typedef name<typename Lhs::value_type, \
- typename Rhs::value_type> elem_op; \
+ typedef name<typename t_Lhs_iterator_helper::value_type, \
+ typename t_Rhs_iterator_helper::value_type \
+ > elem_op; \
\
static assertion_result \
eval( Lhs const& lhs, Rhs const& rhs) \
diff --git a/boost/test/tools/cstring_comparison_op.hpp b/boost/test/tools/cstring_comparison_op.hpp
index 09cbf267e2..50f181d858 100644
--- a/boost/test/tools/cstring_comparison_op.hpp
+++ b/boost/test/tools/cstring_comparison_op.hpp
@@ -37,8 +37,8 @@ namespace op {
#define DEFINE_CSTRING_COMPARISON( oper, name, rev ) \
template<typename Lhs,typename Rhs> \
struct name<Lhs,Rhs,typename boost::enable_if_c< \
- ( unit_test::is_cstring<Lhs>::value \
- && unit_test::is_cstring<Rhs>::value) \
+ ( unit_test::is_cstring_comparable<Lhs>::value \
+ && unit_test::is_cstring_comparable<Rhs>::value) \
>::type > \
{ \
typedef typename unit_test::deduce_cstring<Lhs>::type lhs_char_type; \
@@ -46,13 +46,14 @@ struct name<Lhs,Rhs,typename boost::enable_if_c< \
public: \
typedef assertion_result result_type; \
\
- typedef name<lhs_char_type, rhs_char_type> elem_op; \
+ typedef name< \
+ typename lhs_char_type::value_type, \
+ typename rhs_char_type::value_type> elem_op; \
\
static bool \
eval( Lhs const& lhs, Rhs const& rhs) \
{ \
- return unit_test::basic_cstring<lhs_char_type>(lhs) oper \
- unit_test::basic_cstring<rhs_char_type>(rhs); \
+ return lhs_char_type(lhs) oper rhs_char_type(rhs); \
} \
\
template<typename PrevExprType> \
diff --git a/boost/test/tools/fpc_op.hpp b/boost/test/tools/fpc_op.hpp
index 18364a27b9..b879d218f2 100644
--- a/boost/test/tools/fpc_op.hpp
+++ b/boost/test/tools/fpc_op.hpp
@@ -38,22 +38,19 @@ namespace op {
template<typename OP>
struct fpctraits {
- static const bool cmp_direct = true;
-};
-
-template <typename Lhs, typename Rhs>
-struct fpctraits<op::NE<Lhs,Rhs> > {
- static const bool cmp_direct = false;
+ // indicate if we should perform the operation with a "logical OR"
+ // with the "equality under tolerance".
+ static const bool equality_logical_disjunction = true;
};
template <typename Lhs, typename Rhs>
struct fpctraits<op::LT<Lhs,Rhs> > {
- static const bool cmp_direct = false;
+ static const bool equality_logical_disjunction = false;
};
template <typename Lhs, typename Rhs>
struct fpctraits<op::GT<Lhs,Rhs> > {
- static const bool cmp_direct = false;
+ static const bool equality_logical_disjunction = false;
};
//____________________________________________________________________________//
@@ -62,26 +59,24 @@ struct fpctraits<op::GT<Lhs,Rhs> > {
// ************** set of overloads to select correct fpc algo ************** //
// ************************************************************************** //
// we really only care about EQ vs NE. All other comparisons use direct first
-// and then need EQ. For example a < b (tolerance t) IFF a < b OR a == b (tolerance t)
+// and then need EQ. For example a <= b (tolerance t) IFF a <= b OR a == b (tolerance t)
template <typename FPT, typename Lhs, typename Rhs, typename OP>
inline assertion_result
-compare_fpv( Lhs const& lhs, Rhs const& rhs, OP* )
+compare_fpv( Lhs const& lhs, Rhs const& rhs, OP* cmp_operator)
{
- fpc::close_at_tolerance<FPT> P( fpc_tolerance<FPT>(), fpc::FPC_STRONG );
-
- assertion_result ar( P( lhs, rhs ) );
- if( !ar )
- ar.message() << "Relative difference exceeds tolerance ["
- << P.tested_rel_diff() << " > " << P.fraction_tolerance() << ']';
- return ar;
+ bool result = cmp_operator->eval_direct(lhs, rhs);
+ if(fpctraits<OP>::equality_logical_disjunction) {
+ return result || compare_fpv<FPT>(lhs, rhs, (op::EQ<Lhs, Rhs>*)0);
+ }
+ return result && compare_fpv<FPT>(lhs, rhs, (op::NE<Lhs, Rhs>*)0);
}
//____________________________________________________________________________//
-template <typename FPT, typename OP>
+template <typename FPT, typename Lhs, typename Rhs>
inline assertion_result
-compare_fpv_near_zero( FPT const& fpv, OP* )
+compare_fpv_near_zero( FPT const& fpv, op::EQ<Lhs,Rhs>* )
{
fpc::small_with_tolerance<FPT> P( fpc_tolerance<FPT>() );
@@ -96,22 +91,6 @@ compare_fpv_near_zero( FPT const& fpv, OP* )
template <typename FPT, typename Lhs, typename Rhs>
inline assertion_result
-compare_fpv( Lhs const& lhs, Rhs const& rhs, op::NE<Lhs,Rhs>* )
-{
- fpc::close_at_tolerance<FPT> P( fpc_tolerance<FPT>(), fpc::FPC_WEAK );
-
- assertion_result ar( !P( lhs, rhs ) );
- if( !ar )
- ar.message() << "Relative difference is within tolerance ["
- << P.tested_rel_diff() << " < " << fpc_tolerance<FPT>() << ']';
-
- return ar;
-}
-
-//____________________________________________________________________________//
-
-template <typename FPT, typename Lhs, typename Rhs>
-inline assertion_result
compare_fpv_near_zero( FPT const& fpv, op::NE<Lhs,Rhs>* )
{
fpc::small_with_tolerance<FPT> P( fpc_tolerance<FPT>() );
@@ -126,35 +105,49 @@ compare_fpv_near_zero( FPT const& fpv, op::NE<Lhs,Rhs>* )
template <typename FPT, typename Lhs, typename Rhs>
inline assertion_result
-compare_fpv( Lhs const& lhs, Rhs const& rhs, op::LT<Lhs,Rhs>* )
+compare_fpv( Lhs const& lhs, Rhs const& rhs, op::EQ<Lhs,Rhs>* )
{
- return lhs >= rhs ? assertion_result( false ) : compare_fpv<FPT>( lhs, rhs, (op::NE<Lhs,Rhs>*)0 );
-}
-
-template <typename FPT, typename Lhs, typename Rhs>
-inline assertion_result
-compare_fpv_near_zero( FPT const& fpv, op::LT<Lhs,Rhs>* )
-{
- return fpv >= 0 ? assertion_result( false ) : compare_fpv_near_zero( fpv, (op::NE<Lhs,Rhs>*)0 );
+ if( lhs == 0 ) {
+ return compare_fpv_near_zero( rhs, (op::EQ<Lhs,Rhs>*)0 );
+ }
+ else if( rhs == 0) {
+ return compare_fpv_near_zero( lhs, (op::EQ<Lhs,Rhs>*)0 );
+ }
+ else {
+ fpc::close_at_tolerance<FPT> P( fpc_tolerance<FPT>(), fpc::FPC_STRONG );
+
+ assertion_result ar( P( lhs, rhs ) );
+ if( !ar )
+ ar.message() << "Relative difference exceeds tolerance ["
+ << P.tested_rel_diff() << " > " << P.fraction_tolerance() << ']';
+ return ar;
+ }
}
//____________________________________________________________________________//
template <typename FPT, typename Lhs, typename Rhs>
inline assertion_result
-compare_fpv( Lhs const& lhs, Rhs const& rhs, op::GT<Lhs,Rhs>* )
-{
- return lhs <= rhs ? assertion_result( false ) : compare_fpv<FPT>( lhs, rhs, (op::NE<Lhs,Rhs>*)0 );
-}
-
-template <typename FPT, typename Lhs, typename Rhs>
-inline assertion_result
-compare_fpv_near_zero( FPT const& fpv, op::GT<Lhs,Rhs>* )
+compare_fpv( Lhs const& lhs, Rhs const& rhs, op::NE<Lhs,Rhs>* )
{
- return fpv <= 0 ? assertion_result( false ) : compare_fpv_near_zero( fpv, (op::NE<Lhs,Rhs>*)0 );
+ if( lhs == 0 ) {
+ return compare_fpv_near_zero( rhs, (op::NE<Lhs,Rhs>*)0 );
+ }
+ else if( rhs == 0 ) {
+ return compare_fpv_near_zero( lhs, (op::NE<Lhs,Rhs>*)0 );
+ }
+ else {
+ fpc::close_at_tolerance<FPT> P( fpc_tolerance<FPT>(), fpc::FPC_WEAK );
+
+ assertion_result ar( !P( lhs, rhs ) );
+ if( !ar )
+ ar.message() << "Relative difference is within tolerance ["
+ << P.tested_rel_diff() << " < " << fpc_tolerance<FPT>() << ']';
+
+ return ar;
+ }
}
-
//____________________________________________________________________________//
#define DEFINE_FPV_COMPARISON( oper, name, rev ) \
@@ -177,22 +170,9 @@ public: \
static assertion_result \
eval( Lhs const& lhs, Rhs const& rhs ) \
{ \
- if( lhs == 0 ) \
- { \
- return compare_fpv_near_zero( rhs, (OP*)0 ); \
- } \
- \
- if( rhs == 0 ) \
- { \
- return compare_fpv_near_zero( lhs, (OP*)0 ); \
- } \
- \
- bool direct_res = eval_direct( lhs, rhs ); \
- \
- if( (direct_res && fpctraits<OP>::cmp_direct) || \
- fpc_tolerance<FPT>() == FPT(0) ) \
+ if( fpc_tolerance<FPT>() == FPT(0) ) \
{ \
- return direct_res; \
+ return eval_direct( lhs, rhs ); \
} \
\
return compare_fpv<FPT>( lhs, rhs, (OP*)0 ); \
diff --git a/boost/test/tree/fixture.hpp b/boost/test/tree/fixture.hpp
index 7bca5a8de3..8e07b2aa1d 100644
--- a/boost/test/tree/fixture.hpp
+++ b/boost/test/tree/fixture.hpp
@@ -5,11 +5,8 @@
// See http://www.boost.org/libs/test for the library home page.
//
-// File : $RCSfile$
-//
-// Version : $Revision: 74640 $
-//
-// Description : defines fixture interface and object makers
+/// @file
+/// Defines fixture interface and object makers
// ***************************************************************************
#ifndef BOOST_TEST_TREE_FIXTURE_HPP_100311GER
@@ -22,6 +19,7 @@
#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/function/function0.hpp>
+#include <boost/utility/declval.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
@@ -46,6 +44,83 @@ public:
typedef shared_ptr<test_unit_fixture> test_unit_fixture_ptr;
// ************************************************************************** //
+// ************** fixture helper functions ************** //
+// ************************************************************************** //
+
+namespace impl_fixture {
+
+#if defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
+
+ template<typename U, void (U::*)()> struct fixture_detect {};
+
+ template<typename T>
+ struct has_setup {
+ private:
+ template<typename U> static char Test(fixture_detect<U, &U::setup>*);
+ template<typename U> static int Test(...);
+ public:
+ static const bool value = sizeof(Test<T>(0)) == sizeof(char);
+ };
+
+ template<typename T>
+ struct has_teardown {
+ private:
+ template<typename U> static char Test(fixture_detect<U, &U::teardown>*);
+ template<typename U> static int Test(...);
+ public:
+ static const bool value = sizeof(Test<T>(0)) == sizeof(char);
+ };
+
+#else
+
+ template<typename U> struct fixture_detect { typedef char type; };
+ template<typename T>
+ struct has_setup {
+ private:
+ template<typename U> static auto Test(U*) -> typename fixture_detect<decltype(boost::declval<U>().setup())>::type;
+ template<typename U> static int Test(...);
+ public:
+ static const bool value = sizeof(Test<T>(0)) == sizeof(char);
+ };
+
+ template<typename T>
+ struct has_teardown {
+ private:
+ template<typename U> static auto Test(U*) -> typename fixture_detect<decltype(boost::declval<U>().teardown())>::type;
+ template<typename U> static int Test(...);
+ public:
+ static const bool value = sizeof(Test<T>(0)) == sizeof(char);
+ };
+
+#endif
+
+ template <bool has_setup = false>
+ struct call_setup { template <class U> void operator()(U& ) { } };
+
+ template <>
+ struct call_setup<true> { template <class U> void operator()(U& u) { u.setup(); } };
+
+ template <bool has_teardown = false>
+ struct call_teardown { template <class U> void operator()(U& ) { } };
+
+ template <>
+ struct call_teardown<true> { template <class U> void operator()(U& u) { u.teardown(); } };
+}
+
+//! Calls the fixture "setup" if detected by the compiler, otherwise does nothing.
+template <class U>
+void setup_conditional(U& u) {
+ return impl_fixture::call_setup<impl_fixture::has_setup<U>::value>()(u);
+}
+
+//! Calls the fixture "teardown" if detected by the compiler, otherwise does nothing.
+template <class U>
+void teardown_conditional(U& u) {
+ return impl_fixture::call_teardown<impl_fixture::has_teardown<U>::value>()(u);
+}
+
+
+// ************************************************************************** //
// ************** class_based_fixture ************** //
// ************************************************************************** //
@@ -57,8 +132,8 @@ public:
private:
// Fixture interface
- virtual void setup() { m_inst.reset( new F( m_arg ) ); }
- virtual void teardown() { m_inst.reset(); }
+ virtual void setup() { m_inst.reset( new F( m_arg ) ); setup_conditional(*m_inst); }
+ virtual void teardown() { teardown_conditional(*m_inst); m_inst.reset(); }
// Data members
scoped_ptr<F> m_inst;
@@ -75,8 +150,8 @@ public:
private:
// Fixture interface
- virtual void setup() { m_inst.reset( new F ); }
- virtual void teardown() { m_inst.reset(); }
+ virtual void setup() { m_inst.reset( new F ); setup_conditional(*m_inst); }
+ virtual void teardown() { teardown_conditional(*m_inst); m_inst.reset(); }
// Data members
scoped_ptr<F> m_inst;
diff --git a/boost/test/tree/global_fixture.hpp b/boost/test/tree/global_fixture.hpp
index 2114595929..7c96d34e89 100644
--- a/boost/test/tree/global_fixture.hpp
+++ b/boost/test/tree/global_fixture.hpp
@@ -17,6 +17,7 @@
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/tree/observer.hpp>
+#include <boost/test/tree/fixture.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
@@ -27,13 +28,36 @@ namespace boost {
namespace unit_test {
// ************************************************************************** //
+// ************** global_configuration ************** //
+// ************************************************************************** //
+
+class BOOST_TEST_DECL global_configuration : public test_observer {
+
+public:
+ // Constructor
+ global_configuration();
+
+ // Dtor
+ virtual ~global_configuration();
+
+ // Happens after the framework global observer init has been done
+ virtual int priority() { return 1; }
+};
+
+
+
+// ************************************************************************** //
// ************** global_fixture ************** //
// ************************************************************************** //
-class BOOST_TEST_DECL global_fixture : public test_observer {
+class BOOST_TEST_DECL global_fixture : public test_unit_fixture {
+
public:
// Constructor
global_fixture();
+
+ // Dtor
+ virtual ~global_fixture();
};
//____________________________________________________________________________//
@@ -41,14 +65,48 @@ public:
namespace ut_detail {
template<typename F>
-struct global_fixture_impl : public global_fixture {
+struct global_configuration_impl : public global_configuration {
// Constructor
- global_fixture_impl() : m_fixture( 0 ) {}
+ global_configuration_impl() : m_configuration_observer( 0 ) {
+ }
// test observer interface
- virtual void test_start( counter_t ) { m_fixture = new F; }
- virtual void test_finish() { delete m_fixture; m_fixture = 0; }
- virtual void test_aborted() { delete m_fixture; m_fixture = 0; }
+ virtual void test_start( counter_t ) {
+ m_configuration_observer = new F;
+ }
+
+ // test observer interface
+ virtual void test_finish() {
+ if(m_configuration_observer) {
+ delete m_configuration_observer;
+ m_configuration_observer = 0;
+ }
+ }
+private:
+ // Data members
+ F* m_configuration_observer;
+};
+
+template<typename F>
+struct global_fixture_impl : public global_fixture {
+ // Constructor
+ global_fixture_impl() : m_fixture( 0 ) {
+ }
+
+ // test fixture interface
+ virtual void setup() {
+ m_fixture = new F;
+ setup_conditional(*m_fixture);
+ }
+
+ // test fixture interface
+ virtual void teardown() {
+ if(m_fixture) {
+ teardown_conditional(*m_fixture);
+ }
+ delete m_fixture;
+ m_fixture = 0;
+ }
private:
// Data members
diff --git a/boost/test/tree/observer.hpp b/boost/test/tree/observer.hpp
index 4db930fb07..bd6fc9bff5 100644
--- a/boost/test/tree/observer.hpp
+++ b/boost/test/tree/observer.hpp
@@ -34,7 +34,7 @@ namespace unit_test {
/// Boost.Test framework on the current execution state.
///
/// Several observers can be running at the same time, and it is not unusual to
-/// have interactions among them. The test_observer#priority member function allows the specification
+/// have interactions among them. The @ref test_observer::priority member function allows the specification
/// of a particular order among them (lowest priority executed first, except specified otherwise).
///
class BOOST_TEST_DECL test_observer {
@@ -44,10 +44,8 @@ public:
//!
//! @param[in] number_of_test_cases indicates the number of test cases. Only active
//! test cases are taken into account.
- //!
virtual void test_start( counter_t /* number_of_test_cases */ ) {}
-
//! Called after the framework ends executing the test cases
//!
//! @note The call is made with a reversed priority order.
@@ -98,6 +96,8 @@ public:
//! additional data about the exception.
virtual void exception_caught( execution_exception const& ) {}
+ //! The priority indicates the order at which this observer is initialized
+ //! and tore down in the UTF framework. The order is lowest to highest priority.
virtual int priority() { return 0; }
protected:
diff --git a/boost/test/unit_test_log.hpp b/boost/test/unit_test_log.hpp
index ba998b0ca4..4e6a97b3c2 100644
--- a/boost/test/unit_test_log.hpp
+++ b/boost/test/unit_test_log.hpp
@@ -123,7 +123,7 @@ public:
virtual void exception_caught( execution_exception const& ex );
- virtual int priority() { return 1; }
+ virtual int priority() { return 2; }
// log configuration methods
//! Sets the stream for all loggers
diff --git a/boost/test/unit_test_log_formatter.hpp b/boost/test/unit_test_log_formatter.hpp
index 77fec40aed..79b74e0849 100644
--- a/boost/test/unit_test_log_formatter.hpp
+++ b/boost/test/unit_test_log_formatter.hpp
@@ -248,7 +248,7 @@ public:
// @name Log entry context report
/// Invoked by Unit Test Framework to start log entry context report
-
+ //
/// Unit Test Framework logs for failed assertions and uncaught exceptions context if one was defined by a test module.
/// Context consists of multiple "scopes" identified by description messages assigned by the test module using
/// BOOST_TEST_INFO/BOOST_TEST_CONTEXT statements.
@@ -258,18 +258,20 @@ public:
virtual void entry_context_start( std::ostream& os, log_level l ) = 0;
/// Invoked by Unit Test Framework to report log entry context "scope" description
-
+ //
/// Each "scope" description is reported by separate call to log_entry_context.
/// @param[in] os output stream to write a messages into
+ /// @param[in] l entry log_level, to be used to fine tune the message
/// @param[in] value context "scope" description
/// @see log_entry_start, entry_context_finish
- virtual void log_entry_context( std::ostream& os, const_string value ) = 0;
+ virtual void log_entry_context( std::ostream& os, log_level l, const_string value ) = 0;
/// Invoked by Unit Test Framework to finish log entry context report
-
+ ///
/// @param[in] os output stream to write a messages into
+ /// @param[in] l entry log_level, to be used to fine tune the message
/// @see log_entry_start, entry_context_context
- virtual void entry_context_finish( std::ostream& os ) = 0;
+ virtual void entry_context_finish( std::ostream& os, log_level l ) = 0;
// @}
// @name Log level management
diff --git a/boost/test/unit_test_suite.hpp b/boost/test/unit_test_suite.hpp
index b434fa9f97..13ff804b44 100644
--- a/boost/test/unit_test_suite.hpp
+++ b/boost/test/unit_test_suite.hpp
@@ -143,11 +143,15 @@ struct test_name : public F { void test_method(); }; \
\
static void BOOST_AUTO_TC_INVOKER( test_name )() \
{ \
- BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture entry."); \
+ BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture ctor"); \
test_name t; \
- BOOST_TEST_CHECKPOINT('"' << #test_name << "\" entry."); \
+ BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture setup"); \
+ boost::unit_test::setup_conditional(t); \
+ BOOST_TEST_CHECKPOINT('"' << #test_name << "\" test entry"); \
t.test_method(); \
- BOOST_TEST_CHECKPOINT('"' << #test_name << "\" exit."); \
+ BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture teardown"); \
+ boost::unit_test::teardown_conditional(t); \
+ BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture dtor"); \
} \
\
struct BOOST_AUTO_TC_UNIQUE_ID( test_name ) {}; \
@@ -230,10 +234,11 @@ struct BOOST_AUTO_TC_INVOKER( test_name ) { \
static void run( boost::type<TestType>* = 0 ) \
{ \
BOOST_TEST_CHECKPOINT('"' << #test_name <<"\" fixture entry."); \
- test_name<TestType> t; \
+ test_name<TestType> t; boost::unit_test::setup_conditional(t); \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" entry."); \
t.test_method(); \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" exit."); \
+ boost::unit_test::teardown_conditional(t); \
} \
}; \
\
@@ -290,6 +295,22 @@ void BOOST_JOIN( name, _impl )( boost::type<type_name>* ) \
// ************************************************************************** //
#define BOOST_GLOBAL_FIXTURE( F ) \
+static boost::unit_test::ut_detail::global_configuration_impl<F> BOOST_JOIN( gf_, F ) \
+/**/
+
+// ************************************************************************** //
+// ************** BOOST_TEST_GLOBAL_CONFIGURATION ************** //
+// ************************************************************************** //
+
+#define BOOST_TEST_GLOBAL_CONFIGURATION( F ) \
+static boost::unit_test::ut_detail::global_configuration_impl<F> BOOST_JOIN( gf_, F ) \
+/**/
+
+// ************************************************************************** //
+// ************** BOOST_TEST_GLOBAL_FIXTURE ************** //
+// ************************************************************************** //
+
+#define BOOST_TEST_GLOBAL_FIXTURE( F ) \
static boost::unit_test::ut_detail::global_fixture_impl<F> BOOST_JOIN( gf_, F ) \
/**/
diff --git a/boost/test/utils/algorithm.hpp b/boost/test/utils/algorithm.hpp
index a5491816eb..7f16816c3a 100644
--- a/boost/test/utils/algorithm.hpp
+++ b/boost/test/utils/algorithm.hpp
@@ -15,10 +15,16 @@
// STL
#include <utility>
#include <algorithm> // std::find
-#include <functional> // std::bind1st
+#include <functional> // std::bind1st or std::bind
#include <boost/test/detail/suppress_warnings.hpp>
+#ifdef BOOST_NO_CXX98_BINDERS
+#define BOOST_TEST_BIND1ST(F,A) std::bind( (F), (A), std::placeholders::_1 )
+#else
+#define BOOST_TEST_BIND1ST(F,A) std::bind1st( (F), (A) )
+#endif
+
//____________________________________________________________________________//
namespace boost {
@@ -109,7 +115,7 @@ find_first_not_of( ForwardIterator1 first1, ForwardIterator1 last1,
Predicate pred )
{
while( first1 != last1 ) {
- if( std::find_if( first2, last2, std::bind1st( pred, *first1 ) ) == last2 )
+ if( std::find_if( first2, last2, BOOST_TEST_BIND1ST( pred, *first1 ) ) == last2 )
break;
++first1;
}
@@ -159,9 +165,9 @@ find_last_of( BidirectionalIterator1 first1, BidirectionalIterator1 last1,
return last1;
BidirectionalIterator1 it1 = last1;
- while( --it1 != first1 && std::find_if( first2, last2, std::bind1st( pred, *it1 ) ) == last2 ) {}
+ while( --it1 != first1 && std::find_if( first2, last2, BOOST_TEST_BIND1ST( pred, *it1 ) ) == last2 ) {}
- return it1 == first1 && std::find_if( first2, last2, std::bind1st( pred, *it1 ) ) == last2 ? last1 : it1;
+ return it1 == first1 && std::find_if( first2, last2, BOOST_TEST_BIND1ST( pred, *it1 ) ) == last2 ? last1 : it1;
}
//____________________________________________________________________________//
@@ -206,9 +212,9 @@ find_last_not_of( BidirectionalIterator1 first1, BidirectionalIterator1 last1,
return last1;
BidirectionalIterator1 it1 = last1;
- while( --it1 != first1 && std::find_if( first2, last2, std::bind1st( pred, *it1 ) ) != last2 ) {}
+ while( --it1 != first1 && std::find_if( first2, last2, BOOST_TEST_BIND1ST( pred, *it1 ) ) != last2 ) {}
- return it1 == first1 && std::find_if( first2, last2, std::bind1st( pred, *it1 ) ) == last2 ? last1 : it1;
+ return it1 == first1 && std::find_if( first2, last2, BOOST_TEST_BIND1ST( pred, *it1 ) ) == last2 ? last1 : it1;
}
//____________________________________________________________________________//
diff --git a/boost/test/utils/basic_cstring/basic_cstring.hpp b/boost/test/utils/basic_cstring/basic_cstring.hpp
index d6259990e0..fdd87d5211 100644
--- a/boost/test/utils/basic_cstring/basic_cstring.hpp
+++ b/boost/test/utils/basic_cstring/basic_cstring.hpp
@@ -44,7 +44,7 @@ class basic_cstring {
public:
// Subtypes
typedef ut_detail::bcs_char_traits<CharT> traits_type;
- typedef typename ut_detail::bcs_char_traits<CharT>::std_string std_string;
+ typedef typename traits_type::std_string std_string;
typedef CharT value_type;
typedef typename remove_cv<value_type>::type value_ret_type;
@@ -72,6 +72,7 @@ public:
// Constructors; default copy constructor is generated by compiler
basic_cstring();
+ basic_cstring( basic_cstring const & );
basic_cstring( std_string const& s );
basic_cstring( pointer s );
template<typename LenType>
@@ -188,6 +189,16 @@ basic_cstring<CharT>::basic_cstring()
template<typename CharT>
inline
+basic_cstring<CharT>::basic_cstring(basic_cstring const & s)
+: m_begin( s.m_begin )
+, m_end( s.m_end )
+{
+}
+
+//____________________________________________________________________________//
+
+template<typename CharT>
+inline
basic_cstring<CharT>::basic_cstring( std_string const& s )
: m_begin( s.c_str() )
, m_end( m_begin + s.size() )
diff --git a/boost/test/utils/basic_cstring/compare.hpp b/boost/test/utils/basic_cstring/compare.hpp
index b416b1f2b9..2a256fc6be 100644
--- a/boost/test/utils/basic_cstring/compare.hpp
+++ b/boost/test/utils/basic_cstring/compare.hpp
@@ -76,9 +76,13 @@ case_ins_eq( basic_cstring<CharT> x, basic_cstring<CharT> y )
// ************************************************************************** //
template<class CharT>
-class case_ins_less : public std::binary_function<basic_cstring<CharT>,basic_cstring<CharT>,bool>
+class case_ins_less
{
public:
+ typedef bool result_type;
+ typedef basic_cstring<CharT> first_argument_type;
+ typedef basic_cstring<CharT> second_argument_type;
+
bool operator()( basic_cstring<CharT> x, basic_cstring<CharT> y ) const
{
return x.size() != y.size()
diff --git a/boost/test/utils/is_cstring.hpp b/boost/test/utils/is_cstring.hpp
index 914c7cf673..12326b0418 100644
--- a/boost/test/utils/is_cstring.hpp
+++ b/boost/test/utils/is_cstring.hpp
@@ -23,6 +23,7 @@
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/add_const.hpp>
+#include <boost/test/utils/basic_cstring/basic_cstring_fwd.hpp>
#include <string>
//____________________________________________________________________________//
@@ -51,19 +52,36 @@ struct is_cstring_impl<char*> : public mpl::true_ {};
template<>
struct is_cstring_impl<wchar_t*> : public mpl::true_ {};
+template <typename T, bool is_cstring = is_cstring_impl<typename boost::decay<T>::type>::value >
+struct deduce_cstring_impl;
+
+template <typename T, bool is_cstring >
+struct deduce_cstring_impl<T&, is_cstring> : public deduce_cstring_impl<T, is_cstring>{};
+
+template <typename T, bool is_cstring >
+struct deduce_cstring_impl<T const, is_cstring> : public deduce_cstring_impl<T, is_cstring>{};
+
template <typename T>
-struct deduce_cstring_impl {
+struct deduce_cstring_impl<T, true> {
typedef typename boost::add_const<
typename boost::remove_pointer<
typename boost::decay<T>::type
>::type
- >::type type;
+ >::type U;
+ typedef boost::unit_test::basic_cstring<U> type;
+};
+
+template <typename T>
+struct deduce_cstring_impl< T, false > {
+ typedef typename
+ boost::remove_const<
+ typename boost::remove_reference<T>::type
+ >::type type;
};
template <typename T>
-struct deduce_cstring_impl< std::basic_string<T, std::char_traits<T> > > {
- // const is required here
- typedef typename boost::add_const<T>::type type;
+struct deduce_cstring_impl< std::basic_string<T, std::char_traits<T> >, false > {
+ typedef boost::unit_test::basic_cstring<typename boost::add_const<T>::type> type;
};
} // namespace ut_detail
@@ -71,8 +89,17 @@ struct deduce_cstring_impl< std::basic_string<T, std::char_traits<T> > > {
template<typename T>
struct is_cstring : public ut_detail::is_cstring_impl<typename decay<T>::type> {};
+template<typename T, bool is_cstring = is_cstring<typename boost::decay<T>::type>::value >
+struct is_cstring_comparable: public mpl::false_ {};
+
+template<typename T>
+struct is_cstring_comparable< T, true > : public mpl::true_ {};
+
+template<typename T>
+struct is_cstring_comparable< std::basic_string<T, std::char_traits<T> >, false > : public mpl::true_ {};
+
template<typename T>
-struct is_cstring< std::basic_string<T, std::char_traits<T> > > : public mpl::true_ {};
+struct is_cstring_comparable< boost::unit_test::basic_cstring<T>, false > : public mpl::true_ {};
template <class T>
struct deduce_cstring {
@@ -80,7 +107,7 @@ struct deduce_cstring {
boost::remove_const<
typename boost::remove_reference<T>::type
>::type U;
- typedef typename ut_detail::deduce_cstring_impl<U>::type type;
+ typedef typename ut_detail::deduce_cstring_impl<typename boost::decay<U>::type>::type type;
};
} // namespace unit_test
diff --git a/boost/test/utils/is_forward_iterable.hpp b/boost/test/utils/is_forward_iterable.hpp
index b218e96cba..e8f5d39467 100644
--- a/boost/test/utils/is_forward_iterable.hpp
+++ b/boost/test/utils/is_forward_iterable.hpp
@@ -36,6 +36,7 @@
// Boost
#include <boost/utility/declval.hpp>
+#include <boost/range.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_cv.hpp>
@@ -51,6 +52,9 @@
namespace boost {
namespace unit_test {
+template<typename T>
+struct is_forward_iterable;
+
// ************************************************************************** //
// ************** is_forward_iterable ************** //
// ************************************************************************** //
@@ -65,6 +69,9 @@ struct is_forward_iterable<T const> : public is_forward_iterable<T> {};
template<typename T>
struct is_forward_iterable<T&> : public is_forward_iterable<T> {};
+template<typename T, std::size_t N>
+struct is_forward_iterable< T [N] > : public mpl::true_ {};
+
template<typename T, typename A>
struct is_forward_iterable< std::vector<T, A> > : public mpl::true_ {};
@@ -86,6 +93,7 @@ struct is_forward_iterable< std::string > : public mpl::true_ {};
namespace ut_detail {
+// SFINAE helper
template<typename T>
struct is_present : public mpl::true_ {};
@@ -110,10 +118,12 @@ template <class T>
struct has_member_begin {
private:
struct nil_t {};
- template<typename U> static auto test( U* ) -> decltype(boost::declval<U>().begin());
+ template<typename U> static auto test( U* ) -> decltype(std::begin(boost::declval<U&>())); // does not work with boost::begin
template<typename> static nil_t test( ... );
public:
static bool const value = !std::is_same< decltype(test<T>( nullptr )), nil_t>::value;
+
+
};
//____________________________________________________________________________//
@@ -122,7 +132,7 @@ template <class T>
struct has_member_end {
private:
struct nil_t {};
- template<typename U> static auto test( U* ) -> decltype(boost::declval<U>().end());
+ template<typename U> static auto test( U* ) -> decltype(std::end(boost::declval<U&>())); // does not work with boost::end
template<typename> static nil_t test( ... );
public:
static bool const value = !std::is_same< decltype(test<T>( nullptr )), nil_t>::value;
@@ -134,24 +144,36 @@ template <class T, class enabled = void>
struct is_forward_iterable_impl : std::false_type {
};
-//____________________________________________________________________________//
-
template <class T>
struct is_forward_iterable_impl<
T,
typename std::enable_if<
- is_present<typename T::const_iterator>::value &&
- is_present<typename T::value_type>::value &&
- has_member_size<T>::value &&
- has_member_begin<T>::value &&
- has_member_end<T>::value &&
- !is_cstring<T>::value
+ has_member_begin<T>::value &&
+ has_member_end<T>::value
>::type
> : std::true_type
{};
//____________________________________________________________________________//
+template <class T, class enabled = void>
+struct is_container_forward_iterable_impl : std::false_type {
+};
+
+template <class T>
+struct is_container_forward_iterable_impl<
+ T,
+ typename std::enable_if<
+ is_present<typename T::const_iterator>::value &&
+ is_present<typename T::value_type>::value &&
+ has_member_size<T>::value &&
+ is_forward_iterable_impl<T>::value
+ >::type
+> : is_forward_iterable_impl<T>
+{};
+
+//____________________________________________________________________________//
+
} // namespace ut_detail
/*! Indicates that a specific type implements the forward iterable concept. */
@@ -163,8 +185,54 @@ struct is_forward_iterable {
enum { value = is_fwd_it_t::value };
};
+/*! Indicates that a specific type implements the forward iterable concept. */
+template<typename T>
+struct is_container_forward_iterable {
+ typedef typename std::remove_reference<T>::type T_ref;
+ typedef ut_detail::is_container_forward_iterable_impl<T_ref> is_fwd_it_t;
+ typedef mpl::bool_<is_fwd_it_t::value> type;
+ enum { value = is_fwd_it_t::value };
+};
+
#endif /* defined(BOOST_TEST_FWD_ITERABLE_CXX03) */
+template <typename T, bool is_forward_iterable = is_forward_iterable<T>::value >
+struct bt_iterator_traits;
+
+template <typename T>
+struct bt_iterator_traits< T, true >{
+ BOOST_STATIC_ASSERT((is_forward_iterable<T>::value)); //, "only for forward iterable types");
+ typedef typename T::const_iterator const_iterator;
+ typedef typename T::value_type value_type;
+
+ static const_iterator begin(T const& container) {
+ return container.begin();
+ }
+ static const_iterator end(T const& container) {
+ return container.end();
+ }
+ static std::size_t size(T const& container) {
+ return container.size();
+ }
+};
+
+template <typename T, std::size_t N>
+struct bt_iterator_traits< T [N], true > {
+ typedef typename boost::add_const<T>::type T_const;
+ typedef typename boost::add_pointer<T_const>::type const_iterator;
+ typedef T value_type;
+
+ static const_iterator begin(T_const (&array)[N]) {
+ return &array[0];
+ }
+ static const_iterator end(T_const (&array)[N]) {
+ return &array[N];
+ }
+ static std::size_t size(T_const (&)[N]) {
+ return N;
+ }
+};
+
} // namespace unit_test
} // namespace boost
diff --git a/boost/thread/concurrent_queues/sync_bounded_queue.hpp b/boost/thread/concurrent_queues/sync_bounded_queue.hpp
index e34fa56f37..fd36f8c1a4 100644
--- a/boost/thread/concurrent_queues/sync_bounded_queue.hpp
+++ b/boost/thread/concurrent_queues/sync_bounded_queue.hpp
@@ -127,7 +127,7 @@ namespace concurrent
inline size_type size(lock_guard<mutex>& lk) const BOOST_NOEXCEPT
{
if (full(lk)) return capacity(lk);
- return ((out_+capacity(lk)-in_) % capacity(lk));
+ return ((in_+capacity(lk)-out_) % capacity(lk));
}
inline void throw_if_closed(unique_lock<mutex>&);
@@ -484,7 +484,9 @@ namespace concurrent
queue_op_status sync_bounded_queue<ValueType>::wait_pull_front(ValueType& elem, unique_lock<mutex>& lk)
{
if (empty(lk) && closed(lk)) {return queue_op_status::closed;}
- wait_until_not_empty(lk);
+ bool is_closed = false;
+ wait_until_not_empty(lk, is_closed);
+ if (is_closed) {return queue_op_status::closed;}
pull_front(elem, lk);
return queue_op_status::success;
}
diff --git a/boost/thread/detail/config.hpp b/boost/thread/detail/config.hpp
index 6d1595ebc7..9eff05f5be 100644
--- a/boost/thread/detail/config.hpp
+++ b/boost/thread/detail/config.hpp
@@ -12,7 +12,7 @@
#include <boost/detail/workaround.hpp>
#include <boost/thread/detail/platform.hpp>
-//#define BOOST_THREAD_USEFIXES_TIMESPEC
+#define BOOST_THREAD_USEFIXES_TIMESPEC
//#define BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
//#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
// ATTRIBUTE_MAY_ALIAS
diff --git a/boost/thread/detail/thread.hpp b/boost/thread/detail/thread.hpp
index bd2f149a0e..6424e48385 100644
--- a/boost/thread/detail/thread.hpp
+++ b/boost/thread/detail/thread.hpp
@@ -155,7 +155,15 @@ namespace boost
};
#endif
}
-
+namespace thread_detail {
+#ifdef BOOST_THREAD_USES_CHRONO
+#if defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC) && defined(BOOST_THREAD_USEFIXES_TIMESPEC)
+ typedef chrono::steady_clock internal_clock_t;
+#else
+ typedef chrono::system_clock internal_clock_t;
+#endif
+#endif
+}
class BOOST_THREAD_DECL thread
{
public:
@@ -483,19 +491,13 @@ namespace boost
}
#endif
-#if defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC) && defined(BOOST_THREAD_USEFIXES_TIMESPEC)
- typedef chrono::steady_clock my_clock_t;
-#else
- typedef chrono::system_clock my_clock_t;
-#endif
-
template <class Clock, class Duration>
bool try_join_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
bool joined= false;
do {
- my_clock_t::time_point s_now = my_clock_t::now();
+ thread_detail::internal_clock_t::time_point s_now = thread_detail::internal_clock_t::now();
typename Clock::duration d = ceil<nanoseconds>(t-Clock::now());
if (d <= Clock::duration::zero()) return false; // in case the Clock::time_point t is already reached
joined = try_join_until(s_now + d);
@@ -503,10 +505,10 @@ namespace boost
return true;
}
template <class Duration>
- bool try_join_until(const chrono::time_point<my_clock_t, Duration>& t)
+ bool try_join_until(const chrono::time_point<thread_detail::internal_clock_t, Duration>& t)
{
using namespace chrono;
- typedef time_point<my_clock_t, nanoseconds> nano_sys_tmpt;
+ typedef time_point<thread_detail::internal_clock_t, nanoseconds> nano_sys_tmpt;
return try_join_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
}
#endif
@@ -521,7 +523,7 @@ namespace boost
//}
#ifdef BOOST_THREAD_USES_CHRONO
- bool try_join_until(const chrono::time_point<my_clock_t, chrono::nanoseconds>& tp)
+ bool try_join_until(const chrono::time_point<thread_detail::internal_clock_t, chrono::nanoseconds>& tp)
{
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
return do_try_join_until(rel_time.count());
@@ -542,7 +544,7 @@ namespace boost
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
- bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
+ bool try_join_until(const chrono::time_point<thread_detail::internal_clock_t, chrono::nanoseconds>& tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();
diff --git a/boost/thread/future.hpp b/boost/thread/future.hpp
index 59712c7e2f..7e113e9dee 100644
--- a/boost/thread/future.hpp
+++ b/boost/thread/future.hpp
@@ -1335,7 +1335,7 @@ namespace boost
bool valid() const BOOST_NOEXCEPT
{
- return future_ != 0 && future_->valid();
+ return future_.get() != 0 && future_->valid();
}
void wait() const
@@ -1639,7 +1639,9 @@ namespace boost
base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
{
}
+#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
inline explicit BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other); // EXTENSION
+#endif
explicit BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(shared_future<R>) other) :
base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
@@ -1680,7 +1682,7 @@ namespace boost
// retrieving the value
move_dest_type get()
{
- if (this->future_ == 0)
+ if (this->future_.get() == 0)
{
boost::throw_exception(future_uninitialized());
}
@@ -1700,7 +1702,7 @@ namespace boost
get_or(BOOST_THREAD_RV_REF(R2) v)
{
- if (this->future_ == 0)
+ if (this->future_.get() == 0)
{
boost::throw_exception(future_uninitialized());
}
@@ -1726,7 +1728,7 @@ namespace boost
typename boost::disable_if< is_void<R2>, move_dest_type>::type
get_or(R2 const& v) // EXTENSION
{
- if (this->future_ == 0)
+ if (this->future_.get() == 0)
{
boost::throw_exception(future_uninitialized());
}
@@ -1941,7 +1943,7 @@ namespace boost
// retrieving the value
move_dest_type get()
{
- if (this->future_ == 0)
+ if (this->future_.get() == 0)
{
boost::throw_exception(future_uninitialized());
}
@@ -1957,7 +1959,7 @@ namespace boost
}
move_dest_type get_or(BOOST_THREAD_RV_REF(R) v) // EXTENSION
{
- if (this->future_ == 0)
+ if (this->future_.get() == 0)
{
boost::throw_exception(future_uninitialized());
}
@@ -1976,7 +1978,7 @@ namespace boost
move_dest_type get_or(R const& v) // EXTENSION
{
- if (this->future_ == 0)
+ if (this->future_.get() == 0)
{
boost::throw_exception(future_uninitialized());
}
@@ -4747,7 +4749,7 @@ namespace detail {
inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
BOOST_THREAD_FUTURE<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) {
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
- BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
// keep state alive as we move ourself but hold the lock
shared_ptr<detail::shared_state_base> sentinel(this->future_);
@@ -4811,7 +4813,7 @@ namespace detail {
inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
BOOST_THREAD_FUTURE<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) {
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
- BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
// keep state alive as we move ourself but hold the lock
shared_ptr<detail::shared_state_base> sentinel(this->future_);
@@ -4835,7 +4837,7 @@ namespace detail {
return this->then(this->launch_policy(), boost::forward<F>(func));
#else
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
- BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
// keep state alive as we move ourself but hold the lock
shared_ptr<detail::shared_state_base> sentinel(this->future_);
@@ -4865,7 +4867,7 @@ namespace detail {
BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(launch policy, BOOST_THREAD_FWD_REF(F) func) {
typedef BOOST_THREAD_FUTURE<R2> R;
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
- BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
// keep state alive as we move ourself but hold the lock
shared_ptr<detail::shared_state_base> sentinel(this->future_);
@@ -4939,7 +4941,7 @@ namespace detail {
BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) {
typedef BOOST_THREAD_FUTURE<R2> R;
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
- BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
// keep state alive as we move ourself but hold the lock
shared_ptr<detail::shared_state_base> sentinel(this->future_);
@@ -4965,7 +4967,7 @@ namespace detail {
#else
typedef BOOST_THREAD_FUTURE<R2> R;
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
- BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
// keep state alive as we move ourself but hold the lock
shared_ptr<detail::shared_state_base> sentinel(this->future_);
@@ -4995,7 +4997,7 @@ namespace detail {
shared_future<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) const
{
typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
- BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
if (underlying_cast<int>(policy) & int(launch::async)) {
@@ -5064,7 +5066,7 @@ namespace detail {
shared_future<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const
{
typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
- BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex,
@@ -5085,7 +5087,7 @@ namespace detail {
return this->then(this->launch_policy(), boost::forward<F>(func));
#else
typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
- BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
launch policy = this->launch_policy(lock);
@@ -5257,7 +5259,7 @@ namespace detail
BOOST_THREAD_FUTURE<R2>
BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::unwrap()
{
- BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
// keep state alive as we move ourself but hold the lock
shared_ptr<detail::shared_state_base> sentinel(this->future_);
diff --git a/boost/thread/pthread/condition_variable.hpp b/boost/thread/pthread/condition_variable.hpp
index 46f49ce842..5dcb3a0e38 100644
--- a/boost/thread/pthread/condition_variable.hpp
+++ b/boost/thread/pthread/condition_variable.hpp
@@ -45,9 +45,17 @@ namespace boost
m_.unlock();
m=&m_;
}
- ~lock_on_exit()
+ void deactivate()
{
- if(m)
+ if (m)
+ {
+ m->lock();
+ }
+ m = 0;
+ }
+ ~lock_on_exit() BOOST_NOEXCEPT_IF(false)
+ {
+ if (m)
{
m->lock();
}
@@ -70,10 +78,13 @@ namespace boost
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
pthread_mutex_t* the_mutex = &internal_mutex;
guard.activate(m);
+ res = pthread_cond_wait(&cond,the_mutex);
+ check_for_interruption.check();
+ guard.deactivate();
#else
pthread_mutex_t* the_mutex = m.mutex()->native_handle();
-#endif
res = pthread_cond_wait(&cond,the_mutex);
+#endif
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
this_thread::interruption_point();
@@ -101,10 +112,13 @@ namespace boost
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
pthread_mutex_t* the_mutex = &internal_mutex;
guard.activate(m);
+ cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout);
+ check_for_interruption.check();
+ guard.deactivate();
#else
pthread_mutex_t* the_mutex = m.mutex()->native_handle();
-#endif
cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout);
+#endif
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
this_thread::interruption_point();
@@ -176,6 +190,8 @@ namespace boost
#endif
guard.activate(m);
res=pthread_cond_wait(&cond,&internal_mutex);
+ check_for_interruption.check();
+ guard.deactivate();
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
this_thread::interruption_point();
@@ -404,6 +420,8 @@ namespace boost
#endif
guard.activate(m);
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
+ check_for_interruption.check();
+ guard.deactivate();
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
this_thread::interruption_point();
diff --git a/boost/thread/pthread/pthread_mutex_scoped_lock.hpp b/boost/thread/pthread/pthread_mutex_scoped_lock.hpp
index cdbf8c6740..e3b9990311 100644
--- a/boost/thread/pthread/pthread_mutex_scoped_lock.hpp
+++ b/boost/thread/pthread/pthread_mutex_scoped_lock.hpp
@@ -1,6 +1,6 @@
#ifndef BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP
#define BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP
-// (C) Copyright 2007-8 Anthony Williams
+// (C) Copyright 2007-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -20,41 +20,47 @@ namespace boost
pthread_mutex_t* m;
bool locked;
public:
- explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_):
+ explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_) BOOST_NOEXCEPT:
m(m_),locked(true)
{
BOOST_VERIFY(!pthread_mutex_lock(m));
}
- void unlock()
+ void unlock() BOOST_NOEXCEPT
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
locked=false;
}
-
- ~pthread_mutex_scoped_lock()
+ void check() BOOST_NOEXCEPT
+ {
+ if(locked)
+ {
+ unlock();
+ }
+ }
+ ~pthread_mutex_scoped_lock() BOOST_NOEXCEPT
{
if(locked)
{
unlock();
}
}
-
+
};
class pthread_mutex_scoped_unlock
{
pthread_mutex_t* m;
public:
- explicit pthread_mutex_scoped_unlock(pthread_mutex_t* m_):
+ explicit pthread_mutex_scoped_unlock(pthread_mutex_t* m_) BOOST_NOEXCEPT:
m(m_)
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
}
- ~pthread_mutex_scoped_unlock()
+ ~pthread_mutex_scoped_unlock() BOOST_NOEXCEPT
{
BOOST_VERIFY(!pthread_mutex_lock(m));
}
-
+
};
}
}
diff --git a/boost/thread/pthread/thread_data.hpp b/boost/thread/pthread/thread_data.hpp
index 458bcd5422..836e6927c8 100644
--- a/boost/thread/pthread/thread_data.hpp
+++ b/boost/thread/pthread/thread_data.hpp
@@ -177,6 +177,7 @@ namespace boost
thread_data_base* const thread_info;
pthread_mutex_t* m;
bool set;
+ bool done;
void check_for_interruption()
{
@@ -193,7 +194,7 @@ namespace boost
public:
explicit interruption_checker(pthread_mutex_t* cond_mutex,pthread_cond_t* cond):
thread_info(detail::get_current_thread_data()),m(cond_mutex),
- set(thread_info && thread_info->interrupt_enabled)
+ set(thread_info && thread_info->interrupt_enabled), done(false)
{
if(set)
{
@@ -208,9 +209,10 @@ namespace boost
BOOST_VERIFY(!pthread_mutex_lock(m));
}
}
- ~interruption_checker()
+ void check()
{
- if(set)
+ if ( ! done) {
+ if (set)
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
lock_guard<mutex> guard(thread_info->data_mutex);
@@ -221,6 +223,13 @@ namespace boost
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
}
+ done = true;
+ }
+ }
+
+ ~interruption_checker() BOOST_NOEXCEPT_IF(false)
+ {
+ check();
}
};
#endif
diff --git a/boost/thread/win32/condition_variable.hpp b/boost/thread/win32/condition_variable.hpp
index 23e9e44484..f4b535f74b 100644
--- a/boost/thread/win32/condition_variable.hpp
+++ b/boost/thread/win32/condition_variable.hpp
@@ -142,32 +142,38 @@ namespace boost
struct relocker
{
BOOST_THREAD_NO_COPYABLE(relocker)
- lock_type& lock;
- bool unlocked;
+ lock_type& _lock;
+ bool _unlocked;
relocker(lock_type& lock_):
- lock(lock_),unlocked(false)
+ _lock(lock_), _unlocked(false)
{}
void unlock()
{
- lock.unlock();
- unlocked=true;
+ if ( ! _unlocked )
+ {
+ _lock.unlock();
+ _unlocked=true;
+ }
}
- ~relocker()
+ void lock()
{
- if(unlocked)
- {
- lock.lock();
- }
-
+ if ( _unlocked )
+ {
+ _lock.lock();
+ _unlocked=false;
+ }
+ }
+ ~relocker() BOOST_NOEXCEPT_IF(false)
+ {
+ lock();
}
};
entry_ptr get_wait_entry()
{
- boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
-
+ boost::lock_guard<boost::mutex> lk(internal_mutex);
if(!wake_sem)
{
wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
@@ -190,18 +196,32 @@ namespace boost
struct entry_manager
{
- entry_ptr const entry;
+ entry_ptr entry;
boost::mutex& internal_mutex;
+
BOOST_THREAD_NO_COPYABLE(entry_manager)
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ entry_manager(entry_ptr&& entry_, boost::mutex& mutex_):
+ entry(static_cast< entry_ptr&& >(entry_)), internal_mutex(mutex_)
+ {}
+#else
entry_manager(entry_ptr const& entry_, boost::mutex& mutex_):
entry(entry_), internal_mutex(mutex_)
{}
+#endif
- ~entry_manager()
+ void remove_waiter()
{
+ if (entry) {
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
entry->remove_waiter();
+ entry.reset();
+ }
+ }
+ ~entry_manager() BOOST_NOEXCEPT_IF(false)
+ {
+ remove_waiter();
}
list_entry* operator->()
@@ -215,23 +235,24 @@ namespace boost
template<typename lock_type>
bool do_wait(lock_type& lock,timeout abs_time)
{
- relocker<lock_type> locker(lock);
-
- entry_manager entry(get_wait_entry(), internal_mutex);
-
- locker.unlock();
+ relocker<lock_type> locker(lock);
+ entry_manager entry(get_wait_entry(), internal_mutex);
+ locker.unlock();
- bool woken=false;
- while(!woken)
- {
- if(!entry->wait(abs_time))
- {
- return false;
- }
+ bool woken=false;
+ while(!woken)
+ {
+ if(!entry->wait(abs_time))
+ {
+ return false;
+ }
- woken=entry->woken();
- }
- return woken;
+ woken=entry->woken();
+ }
+ // do it here to avoid throwing on the destructor
+ entry->remove_waiter();
+ locker.lock();
+ return woken;
}
template<typename lock_type,typename predicate_type>
diff --git a/boost/token_iterator.hpp b/boost/token_iterator.hpp
index 584fac28f4..42945d7ee9 100644
--- a/boost/token_iterator.hpp
+++ b/boost/token_iterator.hpp
@@ -39,8 +39,11 @@ namespace boost
>
{
- friend class iterator_core_access;
-
+#ifdef __DCC__
+ friend class boost::iterator_core_access;
+#else
+ friend class iterator_core_access;
+#endif
TokenizerFunc f_;
Iterator begin_;
Iterator end_;
diff --git a/boost/tr1/array.hpp b/boost/tr1/array.hpp
deleted file mode 100644
index 1cd4534ecf..0000000000
--- a/boost/tr1/array.hpp
+++ /dev/null
@@ -1,86 +0,0 @@
-// (C) 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)
-
-#ifndef BOOST_TR1_ARRAY_HPP_INCLUDED
-# define BOOST_TR1_ARRAY_HPP_INCLUDED
-# include <boost/tr1/detail/config.hpp>
-
-#ifdef BOOST_HAS_TR1_ARRAY
-
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next BOOST_TR1_HEADER(array)
-# else
-# include <boost/tr1/detail/config_all.hpp>
-# include BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(array))
-# endif
-
-#else
-
-#include <boost/array.hpp>
-#include <boost/static_assert.hpp>
-#include <boost/type_traits/integral_constant.hpp>
-#include <boost/detail/workaround.hpp>
-
-namespace std{ namespace tr1{
-
-using ::boost::array;
-
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
-// [6.1.3.2] Tuple creation functions
-using ::boost::swap;
-#endif
-
-#if !defined(BOOST_TR1_USE_OLD_TUPLE)
-}} namespace boost{ namespace fusion{
-#endif
-
-// [6.2.2.5] Tuple interface to class template array
-template <class T> struct tuple_size; // forward declaration
-template <int I, class T> struct tuple_element; // forward declaration
-template <class T, size_t N>
-struct tuple_size< ::boost::array<T, N> >
- : public ::boost::integral_constant< ::std::size_t, N>{};
-
-
-template <int I, class T, size_t N>
-struct tuple_element<I, ::boost::array<T, N> >
-{
-#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570))
- BOOST_STATIC_ASSERT(I < (int)N);
- BOOST_STATIC_ASSERT(I >= 0);
-#endif
- typedef T type;
-};
-template <int I, class T, size_t N>
-T& get( ::boost::array<T, N>& a)
-{
- BOOST_STATIC_ASSERT(I < N);
- BOOST_STATIC_ASSERT(I >= 0);
- return a[I];
-}
-
-template <int I, class T, size_t N>
-const T& get(const array<T, N>& a)
-{
- BOOST_STATIC_ASSERT(I < N);
- BOOST_STATIC_ASSERT(I >= 0);
- return a[I];
-}
-
-#if !defined(BOOST_TR1_USE_OLD_TUPLE)
-}} namespace std{ namespace tr1{
-
- using ::boost::fusion::tuple_size;
- using ::boost::fusion::tuple_element;
- using ::boost::fusion::get;
-
-#endif
-
-
-} } // namespaces
-
-#endif
-
-#endif
diff --git a/boost/tr1/cmath.hpp b/boost/tr1/cmath.hpp
deleted file mode 100644
index d692b3c005..0000000000
--- a/boost/tr1/cmath.hpp
+++ /dev/null
@@ -1,267 +0,0 @@
-// (C) Copyright John Maddock 2008.
-// 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_TR1_CMATH_HPP_INCLUDED
-# define BOOST_TR1_CMATH_HPP_INCLUDED
-# include <boost/tr1/detail/config.hpp>
-
-#ifdef BOOST_HAS_TR1_CMATH
-
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next BOOST_TR1_HEADER(cmath)
-# else
-# include <boost/tr1/detail/config_all.hpp>
-# include BOOST_TR1_HEADER(cmath)
-# endif
-
-#else
-
-#include <boost/math/tr1.hpp>
-
-namespace std{ namespace tr1{
-
-using boost::math::tr1::assoc_laguerre;
-using boost::math::tr1::assoc_laguerref;
-using boost::math::tr1::assoc_laguerrel;
-// [5.2.1.2] associated Legendre functions:
-using boost::math::tr1::assoc_legendre;
-using boost::math::tr1::assoc_legendref;
-using boost::math::tr1::assoc_legendrel;
-// [5.2.1.3] beta function:
-using boost::math::tr1::beta;
-using boost::math::tr1::betaf;
-using boost::math::tr1::betal;
-// [5.2.1.4] (complete) elliptic integral of the first kind:
-using boost::math::tr1::comp_ellint_1;
-using boost::math::tr1::comp_ellint_1f;
-using boost::math::tr1::comp_ellint_1l;
-// [5.2.1.5] (complete) elliptic integral of the second kind:
-using boost::math::tr1::comp_ellint_2;
-using boost::math::tr1::comp_ellint_2f;
-using boost::math::tr1::comp_ellint_2l;
-// [5.2.1.6] (complete) elliptic integral of the third kind:
-using boost::math::tr1::comp_ellint_3;
-using boost::math::tr1::comp_ellint_3f;
-using boost::math::tr1::comp_ellint_3l;
-#if 0
-// [5.2.1.7] confluent hypergeometric functions:
-using boost::math::tr1::conf_hyperg;
-using boost::math::tr1::conf_hypergf;
-using boost::math::tr1::conf_hypergl;
-#endif
-// [5.2.1.8] regular modified cylindrical Bessel functions:
-using boost::math::tr1::cyl_bessel_i;
-using boost::math::tr1::cyl_bessel_if;
-using boost::math::tr1::cyl_bessel_il;
-// [5.2.1.9] cylindrical Bessel functions (of the first kind):
-using boost::math::tr1::cyl_bessel_j;
-using boost::math::tr1::cyl_bessel_jf;
-using boost::math::tr1::cyl_bessel_jl;
-// [5.2.1.10] irregular modified cylindrical Bessel functions:
-using boost::math::tr1::cyl_bessel_k;
-using boost::math::tr1::cyl_bessel_kf;
-using boost::math::tr1::cyl_bessel_kl;
-// [5.2.1.11] cylindrical Neumann functions;
-// cylindrical Bessel functions (of the second kind):
-using boost::math::tr1::cyl_neumann;
-using boost::math::tr1::cyl_neumannf;
-using boost::math::tr1::cyl_neumannl;
-// [5.2.1.12] (incomplete) elliptic integral of the first kind:
-using boost::math::tr1::ellint_1;
-using boost::math::tr1::ellint_1f;
-using boost::math::tr1::ellint_1l;
-// [5.2.1.13] (incomplete) elliptic integral of the second kind:
-using boost::math::tr1::ellint_2;
-using boost::math::tr1::ellint_2f;
-using boost::math::tr1::ellint_2l;
-// [5.2.1.14] (incomplete) elliptic integral of the third kind:
-using boost::math::tr1::ellint_3;
-using boost::math::tr1::ellint_3f;
-using boost::math::tr1::ellint_3l;
-// [5.2.1.15] exponential integral:
-using boost::math::tr1::expint;
-using boost::math::tr1::expintf;
-using boost::math::tr1::expintl;
-// [5.2.1.16] Hermite polynomials:
-using boost::math::tr1::hermite;
-using boost::math::tr1::hermitef;
-using boost::math::tr1::hermitel;
-#if 0
-// [5.2.1.17] hypergeometric functions:
-using boost::math::tr1::hyperg;
-using boost::math::tr1::hypergf;
-using boost::math::tr1::hypergl;
-#endif
-// [5.2.1.18] Laguerre polynomials:
-using boost::math::tr1::laguerre;
-using boost::math::tr1::laguerref;
-using boost::math::tr1::laguerrel;
-// [5.2.1.19] Legendre polynomials:
-using boost::math::tr1::legendre;
-using boost::math::tr1::legendref;
-using boost::math::tr1::legendrel;
-// [5.2.1.20] Riemann zeta function:
-using boost::math::tr1::riemann_zeta;
-using boost::math::tr1::riemann_zetaf;
-using boost::math::tr1::riemann_zetal;
-// [5.2.1.21] spherical Bessel functions (of the first kind):
-using boost::math::tr1::sph_bessel;
-using boost::math::tr1::sph_besself;
-using boost::math::tr1::sph_bessell;
-// [5.2.1.22] spherical associated Legendre functions:
-using boost::math::tr1::sph_legendre;
-using boost::math::tr1::sph_legendref;
-using boost::math::tr1::sph_legendrel;
-// [5.2.1.23] spherical Neumann functions;
-// spherical Bessel functions (of the second kind):
-using boost::math::tr1::sph_neumann;
-using boost::math::tr1::sph_neumannf;
-using boost::math::tr1::sph_neumannl;
-
-// types
-using boost::math::tr1::double_t;
-using boost::math::tr1::float_t;
-// functions
-using boost::math::tr1::acosh;
-using boost::math::tr1::acoshf;
-using boost::math::tr1::acoshl;
-using boost::math::tr1::asinh;
-using boost::math::tr1::asinhf;
-using boost::math::tr1::asinhl;
-using boost::math::tr1::atanh;
-using boost::math::tr1::atanhf;
-using boost::math::tr1::atanhl;
-using boost::math::tr1::cbrt;
-using boost::math::tr1::cbrtf;
-using boost::math::tr1::cbrtl;
-using boost::math::tr1::copysign;
-using boost::math::tr1::copysignf;
-using boost::math::tr1::copysignl;
-using boost::math::tr1::erf;
-using boost::math::tr1::erff;
-using boost::math::tr1::erfl;
-using boost::math::tr1::erfc;
-using boost::math::tr1::erfcf;
-using boost::math::tr1::erfcl;
-#if 0
-using boost::math::tr1::exp2;
-using boost::math::tr1::exp2f;
-using boost::math::tr1::exp2l;
-#endif
-using boost::math::tr1::expm1;
-using boost::math::tr1::expm1f;
-using boost::math::tr1::expm1l;
-#if 0
-using boost::math::tr1::fdim;
-using boost::math::tr1::fdimf;
-using boost::math::tr1::fdiml;
-using boost::math::tr1::fma;
-using boost::math::tr1::fmaf;
-using boost::math::tr1::fmal;
-#endif
-using boost::math::tr1::fmax;
-using boost::math::tr1::fmaxf;
-using boost::math::tr1::fmaxl;
-using boost::math::tr1::fmin;
-using boost::math::tr1::fminf;
-using boost::math::tr1::fminl;
-using boost::math::tr1::hypot;
-using boost::math::tr1::hypotf;
-using boost::math::tr1::hypotl;
-#if 0
-using boost::math::tr1::ilogb;
-using boost::math::tr1::ilogbf;
-using boost::math::tr1::ilogbl;
-#endif
-using boost::math::tr1::lgamma;
-using boost::math::tr1::lgammaf;
-using boost::math::tr1::lgammal;
-#if 0
-using boost::math::tr1::llrint;
-using boost::math::tr1::llrintf;
-using boost::math::tr1::llrintl;
-#endif
-using boost::math::tr1::llround;
-using boost::math::tr1::llroundf;
-using boost::math::tr1::llroundl;
-using boost::math::tr1::log1p;
-using boost::math::tr1::log1pf;
-using boost::math::tr1::log1pl;
-#if 0
-using boost::math::tr1::log2;
-using boost::math::tr1::log2f;
-using boost::math::tr1::log2l;
-using boost::math::tr1::logb;
-using boost::math::tr1::logbf;
-using boost::math::tr1::logbl;
-using boost::math::tr1::lrint;
-using boost::math::tr1::lrintf;
-using boost::math::tr1::lrintl;
-#endif
-using boost::math::tr1::lround;
-using boost::math::tr1::lroundf;
-using boost::math::tr1::lroundl;
-#if 0
-using boost::math::tr1::nan;
-using boost::math::tr1::nanf;
-using boost::math::tr1::nanl;
-using boost::math::tr1::nearbyint;
-using boost::math::tr1::nearbyintf;
-using boost::math::tr1::nearbyintl;
-#endif
-using boost::math::tr1::nextafter;
-using boost::math::tr1::nextafterf;
-using boost::math::tr1::nextafterl;
-using boost::math::tr1::nexttoward;
-using boost::math::tr1::nexttowardf;
-using boost::math::tr1::nexttowardl;
-#if 0
-using boost::math::tr1::remainder;
-using boost::math::tr1::remainderf;
-using boost::math::tr1::remainderl;
-using boost::math::tr1::remquo;
-using boost::math::tr1::remquof;
-using boost::math::tr1::remquol;
-using boost::math::tr1::rint;
-using boost::math::tr1::rintf;
-using boost::math::tr1::rintl;
-#endif
-using boost::math::tr1::round;
-using boost::math::tr1::roundf;
-using boost::math::tr1::roundl;
-#if 0
-using boost::math::tr1::scalbln;
-using boost::math::tr1::scalblnf;
-using boost::math::tr1::scalblnl;
-using boost::math::tr1::scalbn;
-using boost::math::tr1::scalbnf;
-using boost::math::tr1::scalbnl;
-#endif
-using boost::math::tr1::tgamma;
-using boost::math::tr1::tgammaf;
-using boost::math::tr1::tgammal;
-using boost::math::tr1::trunc;
-using boost::math::tr1::truncf;
-using boost::math::tr1::truncl;
-// C99 macros defined as C++ templates
-using boost::math::tr1::signbit;
-using boost::math::tr1::fpclassify;
-using boost::math::tr1::isfinite;
-using boost::math::tr1::isinf;
-using boost::math::tr1::isnan;
-using boost::math::tr1::isnormal;
-#if 0
-using boost::math::tr1::isgreater;
-using boost::math::tr1::isgreaterequal;
-using boost::math::tr1::isless;
-using boost::math::tr1::islessequal;
-using boost::math::tr1::islessgreater;
-using boost::math::tr1::isunordered;
-#endif
-} } // namespaces
-
-#endif // BOOST_HAS_TR1_CMATH
-
-#endif // BOOST_TR1_CMATH_HPP_INCLUDED
diff --git a/boost/tr1/complex.hpp b/boost/tr1/complex.hpp
deleted file mode 100644
index 16f7c5da97..0000000000
--- a/boost/tr1/complex.hpp
+++ /dev/null
@@ -1,244 +0,0 @@
-// (C) 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)
-
-#ifndef BOOST_TR1_COMPLEX_HPP_INCLUDED
-# define BOOST_TR1_COMPLEX_HPP_INCLUDED
-# include <boost/tr1/detail/config.hpp>
-# include <complex>
-
-#ifndef BOOST_HAS_TR1_COMPLEX_INVERSE_TRIG
-
-#include <boost/math/complex.hpp>
-
-namespace std {
-namespace tr1 {
-
-using boost::math::acos;
-using boost::math::asin;
-using boost::math::atan;
-using boost::math::acosh;
-using boost::math::asinh;
-using boost::math::atanh;
-using boost::math::fabs;
-
-} }
-
-#else
-
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next BOOST_TR1_HEADER(complex)
-# else
-# include <boost/tr1/detail/config_all.hpp>
-# include BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(complex))
-# endif
-
-#endif
-
-#ifndef BOOST_HAS_TR1_COMPLEX_OVERLOADS
-
-#include <boost/tr1/detail/math_overloads.hpp>
-#include <boost/assert.hpp>
-#include <boost/detail/workaround.hpp>
-#include <boost/config/no_tr1/cmath.hpp>
-
-namespace std{
-
-#ifdef BOOST_NO_STDC_NAMESPACE
- using :: atan2;
-#endif
-
-#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
-template <class T>
-inline BOOST_TR1_MATH_RETURN(double) arg(const T& t)
-{
- return ::std::atan2(0.0, static_cast<double>(t));
-}
-#else
-inline double arg(const double& t)
-{
- return ::std::atan2(0.0, t);
-}
-#endif
-inline long double arg(const long double& t)
-{
- return ::std::atan2(0.0L, static_cast<long double>(t));
-}
-inline float arg(const float& t)
-{
- return ::std::atan2(0.0F, static_cast<float>(t));
-}
-
-#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
-template <class T>
-inline BOOST_TR1_MATH_RETURN(double) norm(const T& t)
-{
- double r = static_cast<double>(t);
- return r*r;
-}
-#else
-inline double norm(const double& t)
-{
- return t*t;
-}
-#endif
-inline long double norm(const long double& t)
-{
- long double l = t;
- return l*l;
-}
-inline float norm(const float& t)
-{
- float f = t;
- return f*f;
-}
-
-#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
-template <class T>
-inline BOOST_TR1_MATH_RETURN(std::complex<double>) conj(const T& t)
-{
- return ::std::conj(std::complex<double>(static_cast<double>(t)));
-}
-#else
-inline std::complex<double> conj(const double& t)
-{
- return ::std::conj(std::complex<double>(t));
-}
-#endif
-inline std::complex<long double> conj(const long double& t)
-{
- return ::std::conj(std::complex<long double>(t));
-}
-inline std::complex<float> conj(const float& t)
-{
- std::complex<float> ct(t);
- ct = ::std::conj(ct);
- return ct;
-}
-
-#if !BOOST_WORKAROUND(__BORLANDC__, <=0x570)
-inline complex<double> polar(const char& rho, const char& theta = 0)
-{ return ::std::polar(static_cast<double>(rho), static_cast<double>(theta)); }
-inline complex<double> polar(const unsigned char& rho, const unsigned char& theta = 0)
-{ return ::std::polar(static_cast<double>(rho), static_cast<double>(theta)); }
-inline complex<double> polar(const signed char& rho, const signed char& theta = 0)
-{ return ::std::polar(static_cast<double>(rho), static_cast<double>(theta)); }
-inline complex<double> polar(const short& rho, const short& theta = 0)
-{ return ::std::polar(static_cast<double>(rho), static_cast<double>(theta)); }
-inline complex<double> polar(const unsigned short& rho, const unsigned short& theta = 0)
-{ return ::std::polar(static_cast<double>(rho), static_cast<double>(theta)); }
-inline complex<double> polar(const int& rho, const int& theta = 0)
-{ return ::std::polar(static_cast<double>(rho), static_cast<double>(theta)); }
-inline complex<double> polar(const unsigned int& rho, const unsigned int& theta = 0)
-{ return ::std::polar(static_cast<double>(rho), static_cast<double>(theta)); }
-inline complex<double> polar(const long& rho, const long& theta = 0)
-{ return ::std::polar(static_cast<double>(rho), static_cast<double>(theta)); }
-inline complex<double> polar(const unsigned long& rho, const unsigned long& theta = 0)
-{ return ::std::polar(static_cast<double>(rho), static_cast<double>(theta)); }
-#ifdef BOOST_HAS_LONG_LONG
-inline complex<double> polar(const long long& rho, const long long& theta = 0)
-{ return ::std::polar(static_cast<double>(rho), static_cast<double>(theta)); }
-inline complex<double> polar(const unsigned long long& rho, const unsigned long long& theta = 0)
-{ return ::std::polar(static_cast<double>(rho), static_cast<double>(theta)); }
-#elif defined(BOOST_HAS_MS_INT64)
-inline complex<double> polar(const __int64& rho, const __int64& theta = 0)
-{ return ::std::polar(static_cast<double>(rho), static_cast<double>(theta)); }
-inline complex<double> polar(const unsigned __int64& rho, const unsigned __int64& theta = 0)
-{ return ::std::polar(static_cast<double>(rho), static_cast<double>(theta)); }
-#endif
-
-template<class T, class U>
-inline complex<typename boost::tr1_detail::promote_to_real<T, U>::type>
- polar(const T& rho, const U& theta)
-{
- typedef typename boost::tr1_detail::promote_to_real<T, U>::type real_type;
- return std::polar(static_cast<real_type>(rho), static_cast<real_type>(theta));
-}
-#endif
-
-#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
-template <class T>
-inline BOOST_TR1_MATH_RETURN(double) imag(const T& )
-{
- return 0;
-}
-#else
-inline double imag(const double& )
-{
- return 0;
-}
-#endif
-inline long double imag(const long double& )
-{
- return 0;
-}
-inline float imag(const float& )
-{
- return 0;
-}
-
-#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
-template <class T>
-inline BOOST_TR1_MATH_RETURN(double) real(const T& t)
-{
- return static_cast<double>(t);
-}
-#else
-inline double real(const double& t)
-{
- return t;
-}
-#endif
-inline long double real(const long double& t)
-{
- return t;
-}
-inline float real(const float& t)
-{
- return t;
-}
-
-template<class T, class U>
-inline complex<typename boost::tr1_detail::largest_real<T, U>::type>
- pow(const complex<T>& x, const complex<U>& y)
-{
- typedef complex<typename boost::tr1_detail::largest_real<T, U>::type> result_type;
- typedef typename boost::mpl::if_<boost::is_same<result_type, complex<T> >, result_type const&, result_type>::type cast1_type;
- typedef typename boost::mpl::if_<boost::is_same<result_type, complex<U> >, result_type const&, result_type>::type cast2_type;
- cast1_type x1(x);
- cast2_type y1(y);
- return std::pow(x1, y1);
-}
-template<class T, class U>
-inline complex<typename boost::tr1_detail::promote_to_real<T, U>::type>
- pow (const complex<T>& x, const U& y)
-{
- typedef typename boost::tr1_detail::promote_to_real<T, U>::type real_type;
- typedef complex<typename boost::tr1_detail::promote_to_real<T, U>::type> result_type;
- typedef typename boost::mpl::if_<boost::is_same<result_type, complex<T> >, result_type const&, result_type>::type cast1_type;
- real_type r = y;
- cast1_type x1(x);
- std::complex<real_type> y1(r);
- return std::pow(x1, y1);
-}
-
-template<class T, class U>
-inline complex<typename boost::tr1_detail::promote_to_real<T, U>::type>
- pow (const T& x, const complex<U>& y)
-{
- typedef typename boost::tr1_detail::promote_to_real<T, U>::type real_type;
- typedef complex<typename boost::tr1_detail::promote_to_real<T, U>::type> result_type;
- typedef typename boost::mpl::if_<boost::is_same<result_type, complex<U> >, result_type const&, result_type>::type cast_type;
- real_type r = x;
- std::complex<real_type> x1(r);
- cast_type y1(y);
- return std::pow(x1, y1);
-}
-
-}
-
-#endif
-
-#endif
-
diff --git a/boost/tr1/detail/config.hpp b/boost/tr1/detail/config.hpp
deleted file mode 100644
index 42069dd257..0000000000
--- a/boost/tr1/detail/config.hpp
+++ /dev/null
@@ -1,173 +0,0 @@
-// (C) Copyright John Maddock 2005-7.
-// 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_TR1_DETAIL_CONFIG_HPP_INCLUDED
-# define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED
-
-#include <cstddef>
-
-#if (defined(__GNUC__) && !(defined(linux) || defined(__linux) || defined(__linux__))) \
- || (!defined(__FreeBSD__) && defined(__GNUC__)) \
- || (!defined(_AIX) && defined(__IBMCPP__) && (__IBMCPP__ >= 800))
- // Disable use of #include_next on Linux as typically we are installed in a
- // directory that is searched *after* the std lib include path.
-#if !defined(BOOST_HAS_INCLUDE_NEXT)
-# define BOOST_HAS_INCLUDE_NEXT
-#endif
-// Need to find out if we're using GLIBC:
-#ifdef BOOST_TR1_UTILITY_INCLUDED
-// Oops we're in a recursive include path!!
-// Need to include utility, or some std lib header,
-// but *not* via <utility> or <boost/config/no_tr1/utility.hpp>
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_CONFIG_RECURSION
-# endif
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <utility>
-# else
-# include BOOST_TR1_STD_HEADER(utility)
-# endif
-# ifdef BOOST_TR1_NO_CONFIG_RECURSION
-# undef BOOST_TR1_NO_CONFIG_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#else
-#include <boost/config/no_tr1/utility.hpp>
-#endif
-#endif
-
-#if defined(__GLIBCXX__) && !defined(BOOST_TR1_PATH)
-# define BOOST_TR1_PATH(name) tr1/name
-#endif
-#if !defined(BOOST_TR1_PATH)
-# define BOOST_TR1_PATH(name) name
-#endif
-
-#define BOOST_TR1_HEADER(name) <BOOST_TR1_PATH(name)>
-
-// Can't use BOOST_WORKAROUND here, it leads to recursive includes:
-#if (defined(__BORLANDC__) && (__BORLANDC__ <= 0x600))
-# define BOOST_TR1_USE_OLD_TUPLE
-#endif
-
-#ifdef __IBMCPP_TR1__
- // turn on support for everything:
-# define BOOST_HAS_TR1
-#endif
-
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-# define BOOST_HAS_TR1_COMPLEX_OVERLOADS
-# define BOOST_HAS_TR1_COMPLEX_INVERSE_TRIG
-#endif
-
-#ifdef BOOST_HAS_TR1
- // turn on support for everything:
-# define BOOST_HAS_TR1_ARRAY
-# define BOOST_HAS_TR1_COMPLEX_OVERLOADS
-# define BOOST_HAS_TR1_COMPLEX_INVERSE_TRIG
-# define BOOST_HAS_TR1_REFERENCE_WRAPPER
-# define BOOST_HAS_TR1_RESULT_OF
-# define BOOST_HAS_TR1_MEM_FN
-# define BOOST_HAS_TR1_BIND
-# define BOOST_HAS_TR1_FUNCTION
-# define BOOST_HAS_TR1_HASH
-# define BOOST_HAS_TR1_SHARED_PTR
-# define BOOST_HAS_TR1_RANDOM
-# define BOOST_HAS_TR1_REGEX
-# define BOOST_HAS_TR1_TUPLE
-# define BOOST_HAS_TR1_TYPE_TRAITS
-# define BOOST_HAS_TR1_UTILITY
-# define BOOST_HAS_TR1_UNORDERED_MAP
-# define BOOST_HAS_TR1_UNORDERED_SET
-# define BOOST_HAS_TR1_CMATH
-
-#endif
-
-#if defined(__MWERKS__) && (__MWERKS__ >= 0x3205)
-//
-// Very preliminary MWCW support, may not be right:
-//
-# define BOOST_HAS_TR1_SHARED_PTR
-# define BOOST_HAS_TR1_REFERENCE_WRAPPER
-# define BOOST_HAS_TR1_FUNCTION
-# define BOOST_HAS_TR1_TUPLE
-# define BOOST_HAS_TR1_RESULT_OF
-#endif
-
-#ifdef BOOST_HAS_GCC_TR1
- // turn on support for everything in gcc 4.0.x:
-# define BOOST_HAS_TR1_ARRAY
-#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 403
-//# define BOOST_HAS_TR1_COMPLEX_OVERLOADS
-# define BOOST_HAS_TR1_COMPLEX_INVERSE_TRIG
-#endif
-# define BOOST_HAS_TR1_REFERENCE_WRAPPER
-# define BOOST_HAS_TR1_RESULT_OF
-# define BOOST_HAS_TR1_MEM_FN
-# define BOOST_HAS_TR1_BIND
-# define BOOST_HAS_TR1_FUNCTION
-# define BOOST_HAS_TR1_HASH
-# define BOOST_HAS_TR1_SHARED_PTR
-#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 403
-# define BOOST_HAS_TR1_RANDOM
-//# define BOOST_HAS_TR1_REGEX
-#ifdef _GLIBCXX_USE_C99_MATH_TR1
-# define BOOST_HAS_TR1_CMATH
-#endif
-#endif
-# define BOOST_HAS_TR1_TUPLE
-# define BOOST_HAS_TR1_TYPE_TRAITS
-# define BOOST_HAS_TR1_UTILITY
-# define BOOST_HAS_TR1_UNORDERED_MAP
-# define BOOST_HAS_TR1_UNORDERED_SET
-
-#endif
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1500) \
- && defined(_MSC_FULL_VER) && \
- !defined(__SGI_STL_PORT) && \
- !defined(_STLPORT_VERSION) && \
- !defined(_RWSTD_VER_STR) && \
- !defined(_RWSTD_VER)
-//
-// MSVC-9.0 defines a not-quite TR1 conforming hash
-// function object in <functional>, so we must define
-// this here, in addition the feature pack for VC9
-// provides a more or less full TR1 implementation:
-//
-# if (defined(_HAS_TR1) && (_HAS_TR1 + 0)) || (_CPPLIB_VER >= 540)
-# define BOOST_HAS_TR1_ARRAY
-# define BOOST_HAS_TR1_REFERENCE_WRAPPER
-# define BOOST_HAS_TR1_RESULT_OF
-# define BOOST_HAS_TR1_MEM_FN
-# define BOOST_HAS_TR1_BIND
-# define BOOST_HAS_TR1_FUNCTION
-# define BOOST_HAS_TR1_HASH
-# define BOOST_HAS_TR1_SHARED_PTR
-# define BOOST_HAS_TR1_RANDOM
-# define BOOST_HAS_TR1_REGEX
-# define BOOST_HAS_TR1_TUPLE
-# define BOOST_HAS_TR1_TYPE_TRAITS
-# define BOOST_HAS_TR1_UTILITY
-# define BOOST_HAS_TR1_UNORDERED_MAP
-# define BOOST_HAS_TR1_UNORDERED_SET
-# else
-# define BOOST_HAS_TR1_HASH
-# endif
-# if _MSC_VER >= 1600
-# define BOOST_HAS_CPP_0X
-# endif
-# if _MSC_VER >= 1700
-# define BOOST_HAS_TR1_COMPLEX_OVERLOADS
-# endif
-#endif
-
-#include <boost/config.hpp>
-
-#endif
-
-
-
diff --git a/boost/tr1/detail/config_all.hpp b/boost/tr1/detail/config_all.hpp
deleted file mode 100644
index bdb0075322..0000000000
--- a/boost/tr1/detail/config_all.hpp
+++ /dev/null
@@ -1,171 +0,0 @@
-// (C) 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)
-
-/*
- * The gcc include path logic is derived from STLport:
- *
- * Copyright (c) 1994
- * Hewlett-Packard Company
- *
- * Copyright (c) 1996-1999
- * Silicon Graphics Computer Systems, Inc.
- *
- * Copyright (c) 1997
- * Moscow Center for SPARC Technology
- *
- * Copyright (c) 1999-2003
- * Boris Fomitchev
- *
- * This material is provided "as is", with absolutely no warranty expressed
- * or implied. Any use is at your own risk.
- *
- * Permission to use or copy this software for any purpose is hereby granted
- * without fee, provided the above notices are retained on all copies.
- * Permission to modify the code and to distribute modified code is granted,
- * provided the above notices are retained, and a notice that the code was
- * modified is included with the above copyright notice.
- *
- */
-
-#ifndef BOOST_TR1_DETAIL_CONFIG_ALL_HPP_INCLUDED
-# define BOOST_TR1_DETAIL_CONFIG_ALL_HPP_INCLUDED
-
-//
-// IMPORTANT: we must figure out the basics, such as how to
-// forward to the real std lib headers *without* including
-// boost/config.hpp or any of the std lib headers. A classic
-// chicken and the egg problem....
-//
-// Including <cstddef> at least lets us detect STLport:
-//
-#include <cstddef>
-
-// Including <cstdlib> allows us to use __GLIBCXX__ to
-// determine the version of the stdc++ library in use
-// under Darwin.
-#include <cstdlib>
-
-# if defined(_RWSTD_VER) && _RWSTD_VER >= 0x04010200
-# if !defined (__SUNPRO_CC) && !defined (__DECCXX)
-# define BOOST_TR1_STD_CHEADER(name) <../include/ansi/name>
-# endif
-# endif
-
-#ifdef __ANDROID__
-# define BOOST_TR1_GCC_INCLUDE_PATH include
-#endif
-
-
-# if (defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) && !defined(__BORLANDC__)
-# ifdef __SUNPRO_CC
- // can't use <../stlport/name> since some compilers put stlport in a different directory:
-# define BOOST_TR1_STD_HEADER(name) <../stlport4/name>
-# elif defined(__PGI)
-# define BOOST_TR1_STD_HEADER(name) <../CC/name>
-# else
-# define BOOST_TR1_STD_HEADER(name) <../stlport/name>
-# endif
-# elif defined(__PATHSCALE__) && (defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER))
-# define BOOST_TR1_STD_HEADER(name) <../include/name>
-
-# elif defined(__SUNPRO_CC) && (defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER))
-# define BOOST_TR1_STD_HEADER(name) <../stdcxx4/name>
-
-# elif defined(__HP_aCC)
- // HP aCC include path:
-# define BOOST_TR1_STD_HEADER(name) <../include_std/name>
-
-# elif defined(__DECCXX)
-# define BOOST_TR1_STD_HEADER(name) <../cxx/name>
-
-# elif defined(__BORLANDC__) && __BORLANDC__ >= 0x570
-# define BOOST_TR1_STD_HEADER(name) <../include/dinkumware/name>
-
-# elif defined(__clang__)
-# define BOOST_TR1_STD_HEADER(name) <../include/name>
-
-# elif defined(_CRAYC)
-# define BOOST_TR1_STD_HEADER(name) <../include/name>
-
-# elif defined(__GNUC__)
-# if defined(BOOST_TR1_GCC_INCLUDE_PATH)
-# define BOOST_TR1_STD_HEADER(name) <../BOOST_TR1_GCC_INCLUDE_PATH/name>
-# elif (defined(__FreeBSD__))
-# define BOOST_TR1_STD_HEADER(name) <../__GNUC__.__GNUC_MINOR__/name>
-# else
-# if ( (__GNUC__ == 3) && (defined(__APPLE_CC__) || defined(__CYGWIN__)))
-# define BOOST_TR1_STD_HEADER(name) <../c++/name>
-# elif ((__GLIBCXX__ == 20050421) && defined(__APPLE_CC__))
- // Some Darwin tools fix libstdc++ at 4.0.0 irrespective of the actual
- // compiler version:
-# define BOOST_TR1_STD_HEADER(name) <../4.0.0/name>
- /*
- * Before version 3.4.0 the 0 patch level was not part of the include path:
- */
-# elif defined (__GNUC_PATCHLEVEL__) && ((__GNUC_PATCHLEVEL__ > 0) || \
- (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
- (__GNUC__ > 3))
-# define BOOST_TR1_STD_HEADER(name) <../__GNUC__.__GNUC_MINOR__.__GNUC_PATCHLEVEL__/name>
-# else
-# define BOOST_TR1_STD_HEADER(name) <../__GNUC__.__GNUC_MINOR__/name>
-# endif
-# endif
-
-# if !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT) && !defined(__ICC) \
- && (defined(__FreeBSD__) || defined(linux) || defined(__linux) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__))
- // Disable use of #include_next on Linux as typically we are installed in a directory that is searched
- // *after* the std lib include path:
-# define BOOST_TR1_DISABLE_INCLUDE_NEXT
-# endif
-
-# else
-# define BOOST_TR1_STD_HEADER(name) <../include/name>
-# endif
-
-#if !defined(BOOST_TR1_STD_CHEADER)
-# define BOOST_TR1_STD_CHEADER(name) BOOST_TR1_STD_HEADER(name)
-#endif
-
-#if defined(__GNUC__) && !defined(BOOST_HAS_INCLUDE_NEXT)
-# define BOOST_HAS_INCLUDE_NEXT
-#endif
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-# define BOOST_HAS_CPP_0X
-#endif
-#if defined(_MSC_VER) && (_MSC_VER >= 1600) && !defined(BOOST_HAS_CPP_0X)
-# define BOOST_HAS_CPP_0X
-#endif
-//
-// We may be in the middle of parsing boost/config.hpp
-// when this header is included, so don't rely on config
-// stuff in the rest of this header...
-//
-// Find our actual std lib:
-//
-#if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-//
-// We don't take this branch if BOOST_TR1_DISABLE_INCLUDE_NEXT
-// is defined as we may be installed in
-// /usr/include, in which case #include_next won't work as our
-// include path will occur AFTER the regular std lib one :-(
-//
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_CONFIG_ALL_RECURSION
-# endif
-# include_next <utility>
-# ifdef BOOST_TR1_NO_CONFIG_ALL_RECURSION
-# undef BOOST_TR1_NO_CONFIG_ALL_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#else
-# include BOOST_TR1_STD_HEADER(utility)
-#endif
-
-#include <boost/tr1/detail/config.hpp>
-
-#endif
-
-
diff --git a/boost/tr1/detail/functor2iterator.hpp b/boost/tr1/detail/functor2iterator.hpp
deleted file mode 100644
index 8911a53137..0000000000
--- a/boost/tr1/detail/functor2iterator.hpp
+++ /dev/null
@@ -1,34 +0,0 @@
-// (C) 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)
-
-#ifndef BOOST_TR1_FUNCTOR_IT_HPP_INCLUDED
-# define BOOST_TR1_FUNCTOR_IT_HPP_INCLUDED
-
-# include <boost/iterator/iterator_facade.hpp>
-
-namespace boost{ namespace tr1_details{
-
-template <class Func, class R>
-struct functor2iterator : boost::iterator_facade<functor2iterator<Func,R>, const R, std::input_iterator_tag>
-{
- functor2iterator() : m_func(0){}
- functor2iterator(Func& f)
- : m_func(&f)
- {
- m_val = (*m_func)();
- }
- const R& dereference()const
- { return m_val; }
- void increment(){ m_val = (*m_func)(); }
- bool equal(const functor2iterator&)const
- { return false; }
-private:
- Func* m_func;
- R m_val;
-};
-
-} }
-
-#endif
diff --git a/boost/tr1/detail/math_overloads.hpp b/boost/tr1/detail/math_overloads.hpp
deleted file mode 100644
index c1a69a443d..0000000000
--- a/boost/tr1/detail/math_overloads.hpp
+++ /dev/null
@@ -1,58 +0,0 @@
-// (C) 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)
-
-#ifndef BOOST_TR1_MATH_OVERLOADS_HPP_INCLUDED
-# define BOOST_TR1_MATH_OVERLOADS_HPP_INCLUDED
-# include <boost/config.hpp>
-
-# ifndef BOOST_NO_SFINAE
-# include <boost/utility/enable_if.hpp>
-# include <boost/type_traits/is_convertible.hpp>
-# define BOOST_TR1_MATH_RETURN(RET) typename ::boost::enable_if< ::boost::is_convertible<T,double>, RET >::type
-# else
-# define BOOST_TR1_MATH_RETURN(RET) RET
-# endif
-
-# include <boost/type_traits/is_floating_point.hpp>
-# include <boost/type_traits/is_same.hpp>
-# include <boost/mpl/if.hpp>
-
-namespace boost{ namespace tr1_detail{
-
-template <class T, class U>
-struct largest_real
-{
- typedef typename boost::mpl::if_<
- boost::is_same<long double, T>,
- long double,
- typename boost::mpl::if_<
- boost::is_same<long double, U>,
- long double,
- typename boost::mpl::if_<
- boost::is_same<double, T>,
- double,
- typename boost::mpl::if_<
- boost::is_same<double, U>,
- double,
- float
- >::type
- >::type
- >::type
- >::type type;
-};
-
-template <class T, class U>
-struct promote_to_real
-{
- typedef typename largest_real<
- typename boost::mpl::if_< boost::is_floating_point<T>, T, double>::type,
- typename boost::mpl::if_< boost::is_floating_point<U>, U, double>::type
- >::type type;
-};
-
-} }
-
-#endif
-
diff --git a/boost/tr1/functional.hpp b/boost/tr1/functional.hpp
deleted file mode 100644
index 0862f4ef98..0000000000
--- a/boost/tr1/functional.hpp
+++ /dev/null
@@ -1,143 +0,0 @@
-// (C) 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)
-
-#ifndef BOOST_TR1_FUNCTIONAL_HPP_INCLUDED
-# define BOOST_TR1_FUNCTIONAL_HPP_INCLUDED
-# include <boost/tr1/detail/config.hpp>
-# include <functional>
-
-#if defined(BOOST_HAS_TR1_REFERENCE_WRAPPER) \
- || defined(BOOST_HAS_TR1_RESULT_OF)\
- || defined(BOOST_HAS_TR1_MEM_FN)\
- || defined(BOOST_HAS_TR1_BIND)\
- || defined(BOOST_HAS_TR1_FUNCTION)\
- || defined(BOOST_HAS_TR1_HASH)
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next BOOST_TR1_HEADER(functional)
-# else
-# include <boost/tr1/detail/config_all.hpp>
-# include BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(functional))
-# endif
-#endif
-
-#ifndef BOOST_HAS_TR1_REFERENCE_WRAPPER
-
-#include <boost/ref.hpp>
-
-namespace std{ namespace tr1{
-
- using ::boost::reference_wrapper;
- using ::boost::ref;
- using ::boost::cref;
-
-} }
-
-#endif // BOOST_HAS_TR1_REFERENCE_WRAPPER
-
-#if !defined(BOOST_HAS_TR1_RESULT_OF)\
- && !defined(BOOST_NO_SFINAE)
-
-//
-// we can only actually include result_of.hpp if the compiler
-// really does support it, otherwise we just get endless errors...
-//
-#include <boost/utility/result_of.hpp>
-
-namespace std{ namespace tr1{
-
- template<class F>
- struct result_of
- : ::boost::tr1_result_of<F>
- {};
-
-} }
-
-#endif // BOOST_HAS_TR1_RESULT_OF
-
-#ifndef BOOST_HAS_TR1_MEM_FN
-// mem_fn:
-#include <boost/mem_fn.hpp>
-
-namespace std{ namespace tr1{
-
-using boost::mem_fn;
-
-} }
-
-#endif // BOOST_HAS_TR1_MEM_FN
-
-
-#ifndef BOOST_HAS_TR1_BIND
-// Bind:
-#include <boost/bind.hpp>
-
-namespace std{ namespace tr1{
-
- using ::boost::is_bind_expression;
- using ::boost::is_placeholder;
- using ::boost::bind;
- namespace placeholders {
-#ifndef BOOST_BIND_NO_PLACEHOLDERS
- using ::_1;
- using ::_2;
- using ::_3;
- using ::_4;
- using ::_5;
- using ::_6;
- using ::_7;
- using ::_8;
- using ::_9;
-#endif
- } // placeholders
-
-} }
-
-#endif
-
-#ifndef BOOST_HAS_TR1_FUNCTION
-// polymorphic function object wrappers:
-#include <boost/function.hpp>
-#include <boost/detail/workaround.hpp>
-
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x582) \
- && !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
-namespace std{ namespace tr1{
-
- using ::boost::bad_function_call;
- using ::boost::function;
- using ::boost::swap;
-
-}}
-#endif
-
-#endif // BOOST_HAS_TR1_FUNCTION
-
-#ifndef BOOST_HAS_TR1_HASH
-//
-// This header can get included by boost/hash.hpp
-// leading to cyclic dependencies. As a workaround
-// we forward declare boost::hash and include
-// the actual header later.
-//
-namespace boost{
-template <class T> struct hash;
-}
-
-namespace std{ namespace tr1{
- //using ::boost::hash;
-
- template <class T>
- struct hash : public boost::hash<T>
- {
- };
-
-}}
-
-#include <boost/functional/hash.hpp>
-
-#endif
-
-#endif
-
diff --git a/boost/tr1/memory.hpp b/boost/tr1/memory.hpp
deleted file mode 100644
index 169087746c..0000000000
--- a/boost/tr1/memory.hpp
+++ /dev/null
@@ -1,72 +0,0 @@
-// (C) 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)
-
-#ifndef BOOST_TR1_MEMORY_HPP_INCLUDED
-# define BOOST_TR1_MEMORY_HPP_INCLUDED
-# include <boost/tr1/detail/config.hpp>
-# include <boost/detail/workaround.hpp>
-# include <memory>
-
-#ifndef BOOST_HAS_TR1_SHARED_PTR
-
-//
-// This header can get included by boost/shared_ptr.hpp which leads
-// to cyclic dependencies, the workaround is to forward declare all
-// the boost components, and then include the actual headers afterwards.
-// This is fragile, but seems to work, and doesn't require modification
-// of boost/shared_ptr.hpp.
-//
-namespace boost{
-
-class bad_weak_ptr;
-template<class T> class weak_ptr;
-template<class T> class shared_ptr;
-template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) BOOST_NOEXCEPT;
-template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b) BOOST_NOEXCEPT;
-template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r) BOOST_NOEXCEPT;
-template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r) BOOST_NOEXCEPT;
-template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r) BOOST_NOEXCEPT;
-template<class D, class T> D * get_deleter(shared_ptr<T> const & p) BOOST_NOEXCEPT;
-template<class T> class enable_shared_from_this;
-
-namespace detail{
-class shared_count;
-class weak_count;
-}
-
-}
-
-namespace std{ namespace tr1{
-
- using ::boost::bad_weak_ptr;
- using ::boost::shared_ptr;
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
- using ::boost::swap;
-#endif
- using ::boost::static_pointer_cast;
- using ::boost::dynamic_pointer_cast;
- using ::boost::const_pointer_cast;
- using ::boost::get_deleter;
- using ::boost::weak_ptr;
- using ::boost::enable_shared_from_this;
-
-} }
-#include <boost/shared_ptr.hpp>
-#include <boost/weak_ptr.hpp>
-#include <boost/enable_shared_from_this.hpp>
-
-#else
-
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next BOOST_TR1_HEADER(memory)
-# else
-# include <boost/tr1/detail/config_all.hpp>
-# include BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(memory))
-# endif
-
-#endif
-
-#endif
-
diff --git a/boost/tr1/random.hpp b/boost/tr1/random.hpp
deleted file mode 100644
index 6e5e34b0fc..0000000000
--- a/boost/tr1/random.hpp
+++ /dev/null
@@ -1,586 +0,0 @@
-// (C) Copyright John Maddock 2005.
-// (C) Copyright Henry S. Warren 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)
-
-#ifndef BOOST_TR1_RANDOM_HPP_INCLUDED
-# define BOOST_TR1_RANDOM_HPP_INCLUDED
-# include <boost/tr1/detail/config.hpp>
-
-#ifdef BOOST_HAS_TR1_RANDOM
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next BOOST_TR1_HEADER(random)
-# else
-# include <boost/tr1/detail/config_all.hpp>
-# include BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(random))
-# endif
-#else
-// Boost.Random:
-#include <boost/random.hpp>
-#ifndef __SUNPRO_CC
- // Sunpros linker complains if we so much as include this...
-# include <boost/nondet_random.hpp>
-#endif
-#include <boost/tr1/detail/functor2iterator.hpp>
-#include <boost/type_traits/is_fundamental.hpp>
-#include <boost/type_traits/is_same.hpp>
-
-namespace std { namespace tr1{
-
-using ::boost::variate_generator;
-
-template<class UIntType, UIntType a, UIntType c, UIntType m>
-class linear_congruential
-{
-private:
- typedef ::boost::random::linear_congruential<UIntType, a, c, m, 0> impl_type;
-public:
- // types
- typedef UIntType result_type;
- // parameter values
- BOOST_STATIC_CONSTANT(UIntType, multiplier = a);
- BOOST_STATIC_CONSTANT(UIntType, increment = c);
- BOOST_STATIC_CONSTANT(UIntType, modulus = m);
- // constructors and member function
- explicit linear_congruential(unsigned long x0 = 1)
- : m_gen(x0){}
- linear_congruential(const linear_congruential& that)
- : m_gen(that.m_gen){}
- template<class Gen> linear_congruential(Gen& g)
- {
- init1(g, ::boost::is_same<Gen,linear_congruential>());
- }
- void seed(unsigned long x0 = 1)
- { m_gen.seed(x0); }
- template<class Gen> void seed(Gen& g)
- {
- init2(g, ::boost::is_fundamental<Gen>());
- }
- result_type min BOOST_PREVENT_MACRO_SUBSTITUTION() const
- { return (m_gen.min)(); }
- result_type max BOOST_PREVENT_MACRO_SUBSTITUTION() const
- { return (m_gen.max)(); }
- result_type operator()()
- {
- return m_gen();
- }
- bool operator==(const linear_congruential& that)const
- { return m_gen == that.m_gen; }
- bool operator!=(const linear_congruential& that)const
- { return m_gen != that.m_gen; }
-
-#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
- template<class CharT, class Traits>
- friend std::basic_ostream<CharT,Traits>&
- operator<<(std::basic_ostream<CharT,Traits>& os,
- const linear_congruential& lcg)
- {
- return os << lcg.m_gen;
- }
-
- template<class CharT, class Traits>
- friend std::basic_istream<CharT,Traits>&
- operator>>(std::basic_istream<CharT,Traits>& is,
- linear_congruential& lcg)
- {
- return is >> lcg.m_gen;
- }
-#endif
-
-private:
- template <class Gen>
- void init1(Gen& g, const ::boost::true_type&)
- {
- m_gen = g.m_gen;
- }
- template <class Gen>
- void init1(Gen& g, const ::boost::false_type&)
- {
- init2(g, ::boost::is_fundamental<Gen>());
- }
- template <class Gen>
- void init2(Gen& g, const ::boost::true_type&)
- {
- m_gen.seed(static_cast<unsigned long>(g));
- }
- template <class Gen>
- void init2(Gen& g, const ::boost::false_type&)
- {
- //typedef typename Gen::result_type gen_rt;
- boost::tr1_details::functor2iterator<Gen, unsigned long> f1(g), f2;
- m_gen.seed(f1, f2);
- }
- impl_type m_gen;
-};
-
-template<class UIntType, int w, int n, int m, int r,
-UIntType a, int u, int s, UIntType b, int t, UIntType c, int l>
-class mersenne_twister
-{
- typedef ::boost::random::mersenne_twister
- <UIntType, w, n, m, r, a, u, s, b, t, c, l, 0> imp_type;
-public:
- // types
- typedef UIntType result_type;
- // parameter values
- BOOST_STATIC_CONSTANT(int, word_size = w);
- BOOST_STATIC_CONSTANT(int, state_size = n);
- BOOST_STATIC_CONSTANT(int, shift_size = m);
- BOOST_STATIC_CONSTANT(int, mask_bits = r);
- BOOST_STATIC_CONSTANT(UIntType, parameter_a = a);
- BOOST_STATIC_CONSTANT(int, output_u = u);
- BOOST_STATIC_CONSTANT(int, output_s = s);
- BOOST_STATIC_CONSTANT(UIntType, output_b = b);
- BOOST_STATIC_CONSTANT(int, output_t = t);
- BOOST_STATIC_CONSTANT(UIntType, output_c = c);
- BOOST_STATIC_CONSTANT(int, output_l = l);
- // constructors and member function
- mersenne_twister(){}
- explicit mersenne_twister(unsigned long value)
- : m_gen(value == 0 ? 5489UL : value){}
- template<class Gen> mersenne_twister(Gen& g)
- {
- init1(g, ::boost::is_same<mersenne_twister,Gen>());
- }
- void seed()
- { m_gen.seed(); }
- void seed(unsigned long value)
- { m_gen.seed(value == 0 ? 5489UL : value); }
- template<class Gen> void seed(Gen& g)
- { init2(g, ::boost::is_fundamental<Gen>()); }
- result_type min BOOST_PREVENT_MACRO_SUBSTITUTION() const
- { return (m_gen.min)(); }
- result_type max BOOST_PREVENT_MACRO_SUBSTITUTION() const
- { return (m_gen.max)(); }
- result_type operator()()
- { return m_gen(); }
- bool operator==(const mersenne_twister& that)const
- { return m_gen == that.m_gen; }
- bool operator!=(const mersenne_twister& that)const
- { return m_gen != that.m_gen; }
-
-#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
- template<class CharT, class Traits>
- friend std::basic_ostream<CharT,Traits>&
- operator<<(std::basic_ostream<CharT,Traits>& os,
- const mersenne_twister& lcg)
- {
- return os << lcg.m_gen;
- }
-
- template<class CharT, class Traits>
- friend std::basic_istream<CharT,Traits>&
- operator>>(std::basic_istream<CharT,Traits>& is,
- mersenne_twister& lcg)
- {
- return is >> lcg.m_gen;
- }
-#endif
-private:
- template <class Gen>
- void init1(Gen& g, const ::boost::true_type&)
- {
- m_gen = g.m_gen;
- }
- template <class Gen>
- void init1(Gen& g, const ::boost::false_type&)
- {
- init2(g, ::boost::is_fundamental<Gen>());
- }
- template <class Gen>
- void init2(Gen& g, const ::boost::true_type&)
- {
- m_gen.seed(static_cast<unsigned long>(g == 0 ? 4357UL : g));
- }
- template <class Gen>
- void init2(Gen& g, const ::boost::false_type&)
- {
- m_gen.seed(g);
- }
- imp_type m_gen;
-};
-
-template<class IntType, IntType m, int s, int r>
-class subtract_with_carry
-{
-public:
- // types
- typedef IntType result_type;
- // parameter values
- BOOST_STATIC_CONSTANT(IntType, modulus = m);
- BOOST_STATIC_CONSTANT(int, long_lag = r);
- BOOST_STATIC_CONSTANT(int, short_lag = s);
-
- // constructors and member function
- subtract_with_carry(){}
- explicit subtract_with_carry(unsigned long value)
- : m_gen(value == 0 ? 19780503UL : value){}
- template<class Gen> subtract_with_carry(Gen& g)
- { init1(g, ::boost::is_same<Gen, subtract_with_carry<IntType, m, s, r> >()); }
- void seed(unsigned long value = 19780503ul)
- { m_gen.seed(value == 0 ? 19780503UL : value); }
- template<class Gen> void seed(Gen& g)
- { init2(g, ::boost::is_fundamental<Gen>()); }
- result_type min BOOST_PREVENT_MACRO_SUBSTITUTION() const
- { return (m_gen.min)(); }
- result_type max BOOST_PREVENT_MACRO_SUBSTITUTION() const
- { return (m_gen.max)(); }
- result_type operator()()
- { return m_gen(); }
- bool operator==(const subtract_with_carry& that)const
- { return m_gen == that.m_gen; }
- bool operator!=(const subtract_with_carry& that)const
- { return m_gen != that.m_gen; }
-
-#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
- template<class CharT, class Traits>
- friend std::basic_ostream<CharT,Traits>&
- operator<<(std::basic_ostream<CharT,Traits>& os,
- const subtract_with_carry& lcg)
- {
- return os << lcg.m_gen;
- }
-
- template<class CharT, class Traits>
- friend std::basic_istream<CharT,Traits>&
- operator>>(std::basic_istream<CharT,Traits>& is,
- subtract_with_carry& lcg)
- {
- return is >> lcg.m_gen;
- }
-#endif
-private:
- template <class Gen>
- void init1(Gen& g, const ::boost::true_type&)
- {
- m_gen = g.m_gen;
- }
- template <class Gen>
- void init1(Gen& g, const ::boost::false_type&)
- {
- init2(g, ::boost::is_fundamental<Gen>());
- }
- template <class Gen>
- void init2(Gen& g, const ::boost::true_type&)
- {
- m_gen.seed(static_cast<unsigned long>(g == 0 ? 19780503UL : g));
- }
- template <class Gen>
- void init2(Gen& g, const ::boost::false_type&)
- {
- m_gen.seed(g);
- }
- ::boost::random::subtract_with_carry<IntType, m, s, r, 0> m_gen;
-};
-
-template<class RealType, int w, int s, int r>
-class subtract_with_carry_01
-{
-public:
- // types
- typedef RealType result_type;
- // parameter values
- BOOST_STATIC_CONSTANT(int, word_size = w);
- BOOST_STATIC_CONSTANT(int, long_lag = r);
- BOOST_STATIC_CONSTANT(int, short_lag = s);
-
- // constructors and member function
- subtract_with_carry_01(){}
- explicit subtract_with_carry_01(unsigned long value)
- : m_gen(value == 0 ? 19780503UL : value){}
- template<class Gen> subtract_with_carry_01(Gen& g)
- { init1(g, ::boost::is_same<Gen, subtract_with_carry_01<RealType, w, s, r> >()); }
- void seed(unsigned long value = 19780503UL)
- { m_gen.seed(value == 0 ? 19780503UL : value); }
- template<class Gen> void seed(Gen& g)
- { init2(g, ::boost::is_fundamental<Gen>()); }
- result_type min BOOST_PREVENT_MACRO_SUBSTITUTION() const
- { return (m_gen.min)(); }
- result_type max BOOST_PREVENT_MACRO_SUBSTITUTION() const
- { return (m_gen.max)(); }
- result_type operator()()
- { return m_gen(); }
- bool operator==(const subtract_with_carry_01& that)const
- { return m_gen == that.m_gen; }
- bool operator!=(const subtract_with_carry_01& that)const
- { return m_gen != that.m_gen; }
-
-#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
- template<class CharT, class Traits>
- friend std::basic_ostream<CharT,Traits>&
- operator<<(std::basic_ostream<CharT,Traits>& os,
- const subtract_with_carry_01& lcg)
- {
- return os << lcg.m_gen;
- }
-
- template<class CharT, class Traits>
- friend std::basic_istream<CharT,Traits>&
- operator>>(std::basic_istream<CharT,Traits>& is,
- subtract_with_carry_01& lcg)
- {
- return is >> lcg.m_gen;
- }
-#endif
-private:
- template <class Gen>
- void init1(Gen& g, const ::boost::true_type&)
- {
- m_gen = g.m_gen;
- }
- template <class Gen>
- void init1(Gen& g, const ::boost::false_type&)
- {
- init2(g, ::boost::is_fundamental<Gen>());
- }
- template <class Gen>
- void init2(Gen& g, const ::boost::true_type&)
- {
- m_gen.seed(static_cast<unsigned long>(g == 0 ? 19780503UL : g));
- }
- template <class Gen>
- void init2(Gen& g, const ::boost::false_type&)
- {
- //typedef typename Gen::result_type gen_rt;
- boost::tr1_details::functor2iterator<Gen, unsigned long> f1(g), f2;
- m_gen.seed(f1, f2);
- }
- ::boost::random::subtract_with_carry_01<RealType, w, s, r, 0> m_gen;
-};
-
-using ::boost::random::discard_block;
-
-template<class UniformRandomNumberGenerator1, int s1, class UniformRandomNumberGenerator2, int s2>
-class xor_combine
-{
-public:
- // types
- typedef UniformRandomNumberGenerator1 base1_type;
- typedef UniformRandomNumberGenerator2 base2_type;
- typedef unsigned long result_type;
- // parameter values
- BOOST_STATIC_CONSTANT(int, shift1 = s1);
- BOOST_STATIC_CONSTANT(int, shift2 = s2);
- // constructors and member function
- xor_combine(){ init_minmax(); }
- xor_combine(const base1_type & rng1, const base2_type & rng2)
- : m_b1(rng1), m_b2(rng2) { init_minmax(); }
- xor_combine(unsigned long s)
- : m_b1(s), m_b2(s+1) { init_minmax(); }
- template<class Gen> xor_combine(Gen& g)
- {
- init_minmax();
- init1(g, ::boost::is_same<Gen, xor_combine<UniformRandomNumberGenerator1, s1, UniformRandomNumberGenerator2, s2> >());
- }
- void seed()
- {
- m_b1.seed();
- m_b2.seed();
- }
- void seed(unsigned long s)
- {
- m_b1.seed(s);
- m_b2.seed(s+1);
- }
- template<class Gen> void seed(Gen& g)
- {
- init2(g, ::boost::is_fundamental<Gen>());
- }
-
- const base1_type& base1() const
- { return m_b1; }
- const base2_type& base2() const
- { return m_b2; }
- result_type min BOOST_PREVENT_MACRO_SUBSTITUTION() const
- { return m_min; }
- result_type max BOOST_PREVENT_MACRO_SUBSTITUTION() const
- { return m_max; }
- result_type operator()()
- { return (m_b1() << s1) ^ (m_b2() << s2); }
-
- bool operator == (const xor_combine& that)const
- { return (m_b1 == that.m_b1) && (m_b2 == that.m_b2); }
- bool operator != (const xor_combine& that)const
- { return !(*this == that); }
-
-#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
- template<class CharT, class Traits>
- friend std::basic_ostream<CharT,Traits>&
- operator<<(std::basic_ostream<CharT,Traits>& os,
- const xor_combine& lcg)
- {
- return os << lcg.m_b1 << " " << lcg.m_b2;
- }
-
- template<class CharT, class Traits>
- friend std::basic_istream<CharT,Traits>&
- operator>>(std::basic_istream<CharT,Traits>& is,
- xor_combine& lcg)
- {
- return is >> lcg.m_b1 >> lcg.m_b2;
- }
-#endif
-
-private:
- void init_minmax();
- base1_type m_b1;
- base2_type m_b2;
- result_type m_min;
- result_type m_max;
-
- template <class Gen>
- void init1(Gen& g, const ::boost::true_type&)
- {
- m_b1 = g.m_b1;
- m_b2 = g.m_b2;
- }
- template <class Gen>
- void init1(Gen& g, const ::boost::false_type&)
- {
- init2(g, ::boost::is_fundamental<Gen>());
- }
- template <class Gen>
- void init2(Gen& g, const ::boost::true_type&)
- {
- m_b1.seed(static_cast<unsigned long>(g));
- m_b2.seed(static_cast<unsigned long>(g));
- }
- template <class Gen>
- void init2(Gen& g, const ::boost::false_type&)
- {
- m_b1.seed(g);
- m_b2.seed(g);
- }
-};
-
-template<class UniformRandomNumberGenerator1, int s1, class UniformRandomNumberGenerator2, int s2>
-void xor_combine<UniformRandomNumberGenerator1, s1, UniformRandomNumberGenerator2, s2>::init_minmax()
-{
- //
- // The following code is based on that given in "Hacker's Delight"
- // by Henry S. Warren, (Addison-Wesley, 2003), and at
- // http://www.hackersdelight.org/index.htm.
- // Used here by permission.
- //
- // calculation of minimum value:
- //
- result_type a = (m_b1.min)() << s1;
- result_type b = (m_b1.max)() << s1;
- result_type c = (m_b2.min)() << s2;
- result_type d = (m_b2.max)() << s2;
- result_type m, temp;
-
- m = 0x1uL << ((sizeof(result_type) * CHAR_BIT) - 1);
- while (m != 0) {
- if (~a & c & m) {
- temp = (a | m) & (static_cast<result_type>(0u) - m);
- if (temp <= b) a = temp;
- }
- else if (a & ~c & m) {
- temp = (c | m) & (static_cast<result_type>(0u) - m);
- if (temp <= d) c = temp;
- }
- m >>= 1;
- }
- m_min = a ^ c;
-
- //
- // calculation of maximum value:
- //
- if((((std::numeric_limits<result_type>::max)() >> s1) < (m_b1.max)())
- || ((((std::numeric_limits<result_type>::max)()) >> s2) < (m_b2.max)()))
- {
- m_max = (std::numeric_limits<result_type>::max)();
- return;
- }
- a = (m_b1.min)() << s1;
- b = (m_b1.max)() << s1;
- c = (m_b2.min)() << s2;
- d = (m_b2.max)() << s2;
-
- m = 0x1uL << ((sizeof(result_type) * CHAR_BIT) - 1);
-
- while (m != 0) {
- if (b & d & m) {
- temp = (b - m) | (m - 1);
- if (temp >= a) b = temp;
- else {
- temp = (d - m) | (m - 1);
- if (temp >= c) d = temp;
- }
- }
- m = m >> 1;
- }
- m_max = b ^ d;
-}
-
-typedef linear_congruential< ::boost::int32_t, 16807, 0, 2147483647> minstd_rand0;
-typedef linear_congruential< ::boost::int32_t, 48271, 0, 2147483647> minstd_rand;
-typedef mersenne_twister< ::boost::uint32_t, 32,624,397,31,0x9908b0df,11,7,0x9d2c5680,15,0xefc60000,18> mt19937;
-typedef subtract_with_carry_01<float, 24, 10, 24> ranlux_base_01;
-typedef subtract_with_carry_01<double, 48, 10, 24> ranlux64_base_01;
-typedef discard_block<subtract_with_carry< ::boost::int32_t, (1<<24), 10, 24>, 223, 24> ranlux3;
-typedef discard_block<subtract_with_carry< ::boost::int32_t, (1<<24), 10, 24>, 389, 24> ranlux4;
-typedef discard_block<subtract_with_carry_01<float, 24, 10, 24>, 223, 24> ranlux3_01;
-typedef discard_block<subtract_with_carry_01<float, 24, 10, 24>, 389, 24> ranlux4_01;
-
-#ifndef __SUNPRO_CC
-using ::boost::random_device;
-#endif
-using ::boost::uniform_int;
-
-class bernoulli_distribution
-{
-public:
- // types
- typedef int input_type;
- typedef bool result_type;
- // constructors and member function
- explicit bernoulli_distribution(double p = 0.5)
- : m_dist(p){}
- double p() const
- { return m_dist.p(); }
- void reset()
- { m_dist.reset(); }
- template<class UniformRandomNumberGenerator>
- result_type operator()(UniformRandomNumberGenerator& urng)
- {
- return m_dist(urng);
- }
-#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
- template<class CharT, class Traits>
- friend std::basic_ostream<CharT,Traits>&
- operator<<(std::basic_ostream<CharT,Traits>& os,
- const bernoulli_distribution& lcg)
- {
- return os << lcg.m_dist;
- }
-
- template<class CharT, class Traits>
- friend std::basic_istream<CharT,Traits>&
- operator>>(std::basic_istream<CharT,Traits>& is,
- bernoulli_distribution& lcg)
- {
- return is >> lcg.m_dist;
- }
-#endif
-
-private:
- ::boost::bernoulli_distribution<double> m_dist;
-};
-//using ::boost::bernoulli_distribution;
-using ::boost::geometric_distribution;
-using ::boost::poisson_distribution;
-using ::boost::binomial_distribution;
-using ::boost::uniform_real;
-using ::boost::exponential_distribution;
-using ::boost::normal_distribution;
-using ::boost::gamma_distribution;
-
-} }
-
-#endif
-
-#endif
-
diff --git a/boost/tr1/regex.hpp b/boost/tr1/regex.hpp
deleted file mode 100644
index f682d7a751..0000000000
--- a/boost/tr1/regex.hpp
+++ /dev/null
@@ -1,147 +0,0 @@
-// (C) 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)
-
-#ifndef BOOST_TR1_REGEX_HPP_INCLUDED
-# define BOOST_TR1_REGEX_HPP_INCLUDED
-# include <boost/tr1/detail/config.hpp>
-
-#ifdef BOOST_HAS_TR1_REGEX
-
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next BOOST_TR1_HEADER(regex)
-# else
-# include <boost/tr1/detail/config_all.hpp>
-# include BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(regex))
-# endif
-
-#else
-
-#include <boost/regex.hpp>
-
-namespace std{ namespace tr1{
-
-// [7.5] Regex constants
-namespace regex_constants {
-
-using ::boost::regex_constants::syntax_option_type;
-using ::boost::regex_constants::icase;
-using ::boost::regex_constants::nosubs;
-using ::boost::regex_constants::optimize;
-using ::boost::regex_constants::collate;
-using ::boost::regex_constants::ECMAScript;
-using ::boost::regex_constants::basic;
-using ::boost::regex_constants::extended;
-using ::boost::regex_constants::awk;
-using ::boost::regex_constants::grep;
-using ::boost::regex_constants::egrep;
-
-using ::boost::regex_constants::match_flag_type;
-using ::boost::regex_constants::match_default;
-using ::boost::regex_constants::match_not_bol;
-using ::boost::regex_constants::match_not_eol;
-using ::boost::regex_constants::match_not_bow;
-using ::boost::regex_constants::match_not_eow;
-using ::boost::regex_constants::match_any;
-using ::boost::regex_constants::match_not_null;
-using ::boost::regex_constants::match_continuous;
-using ::boost::regex_constants::match_prev_avail;
-using ::boost::regex_constants::format_default;
-using ::boost::regex_constants::format_sed;
-using ::boost::regex_constants::format_no_copy;
-using ::boost::regex_constants::format_first_only;
-
-using ::boost::regex_constants::error_type;
-using ::boost::regex_constants::error_collate;
-using ::boost::regex_constants::error_ctype;
-using ::boost::regex_constants::error_escape;
-using ::boost::regex_constants::error_backref;
-using ::boost::regex_constants::error_brack;
-using ::boost::regex_constants::error_paren;
-using ::boost::regex_constants::error_brace;
-using ::boost::regex_constants::error_badbrace;
-using ::boost::regex_constants::error_range;
-using ::boost::regex_constants::error_space;
-using ::boost::regex_constants::error_badrepeat;
-using ::boost::regex_constants::error_complexity;
-using ::boost::regex_constants::error_stack;
-
-} // namespace regex_constants
-
-// [7.6] Class regex_error
-using ::boost::regex_error;
-
-// [7.7] Class template regex_traits
-using ::boost::regex_traits;
-
-// [7.8] Class template basic_regex
-using ::boost::basic_regex;
-using ::boost::regex;
-#ifndef BOOST_NO_WREGEX
-using ::boost::wregex;
-#endif
-
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
-// [7.8.6] basic_regex swap
-using ::boost::swap;
-#endif
-
-// [7.9] Class template sub_match
-using ::boost::sub_match;
-
-using ::boost::csub_match;
-#ifndef BOOST_NO_WREGEX
-using ::boost::wcsub_match;
-#endif
-using ::boost::ssub_match;
-#ifndef BOOST_NO_WREGEX
-using ::boost::wssub_match;
-#endif
-
-// [7.10] Class template match_results
-using ::boost::match_results;
-using ::boost::cmatch;
-#ifndef BOOST_NO_WREGEX
-using ::boost::wcmatch;
-#endif
-using ::boost::smatch;
-#ifndef BOOST_NO_WREGEX
-using ::boost::wsmatch;
-#endif
-
-using ::boost::regex_match;
-
-// [7.11.3] Function template regex_search
-using ::boost::regex_search;
-
-// [7.11.4] Function template regex_replace
-using ::boost::regex_replace;
-
-// [7.12.1] Class template regex_iterator
-using ::boost::regex_iterator;
-using ::boost::cregex_iterator;
-#ifndef BOOST_NO_WREGEX
-using ::boost::wcregex_iterator;
-#endif
-using ::boost::sregex_iterator;
-#ifndef BOOST_NO_WREGEX
-using ::boost::wsregex_iterator;
-#endif
-
-// [7.12.2] Class template regex_token_iterator
-using ::boost::regex_token_iterator;
-using ::boost::cregex_token_iterator;
-#ifndef BOOST_NO_WREGEX
-using ::boost::wcregex_token_iterator;
-#endif
-using ::boost::sregex_token_iterator;
-#ifndef BOOST_NO_WREGEX
-using ::boost::wsregex_token_iterator;
-#endif
-
-} } // namespaces
-
-#endif
-
-#endif
diff --git a/boost/tr1/tr1/algorithm b/boost/tr1/tr1/algorithm
deleted file mode 100644
index 05252ff9f2..0000000000
--- a/boost/tr1/tr1/algorithm
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_algorithm_INCLUDED
-# define BOOST_TR1_algorithm_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_algorithm_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <algorithm>
-# else
-# include BOOST_TR1_STD_HEADER(algorithm)
-# endif
-# ifdef BOOST_TR1_NO_algorithm_RECURSION
-# undef BOOST_TR1_NO_algorithm_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/array b/boost/tr1/tr1/array
deleted file mode 100644
index 0dc4b3c626..0000000000
--- a/boost/tr1/tr1/array
+++ /dev/null
@@ -1,34 +0,0 @@
-// (C) 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)
-
-
-#if !defined(BOOST_TR1_ARRAY_INCLUDED)
-# define BOOST_TR1_ARRAY_INCLUDED
-# include <boost/tr1/detail/config_all.hpp>
-
-# ifdef BOOST_HAS_CPP_0X
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <array>
-# else
-# include BOOST_TR1_STD_HEADER(array)
-# endif
-# endif
-
-# if !defined(BOOST_TR1_NO_RECURSION)
-# define BOOST_TR1_NO_RECURSION
-# ifdef BOOST_HAS_TR1_ARRAY
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next BOOST_TR1_HEADER(array)
-# else
-# include BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(array))
-# endif
-# else
-# include <boost/tr1/array.hpp>
-# endif
-# undef BOOST_TR1_NO_RECURSION
-#endif
-#endif
-
-
diff --git a/boost/tr1/tr1/bcc32/array.h b/boost/tr1/tr1/bcc32/array.h
deleted file mode 100644
index 8897c7147e..0000000000
--- a/boost/tr1/tr1/bcc32/array.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// (C) 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)
-
-//
-// Forwarding header for Borland C++:
-//
-#if !defined(BOOST_TR1_ARRAY_H_INCLUDED)
-# define BOOST_TR1_ARRAY_H_INCLUDED
-# include <array.>
-#endif
-
diff --git a/boost/tr1/tr1/bcc32/random.h b/boost/tr1/tr1/bcc32/random.h
deleted file mode 100644
index dd17f6fbc8..0000000000
--- a/boost/tr1/tr1/bcc32/random.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// (C) 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)
-
-//
-// Forwarding header for Borland C++:
-//
-#if !defined(BOOST_TR1_RANDOM_H_INCLUDED)
-# define BOOST_TR1_RANDOM_H_INCLUDED
-# include <random.>
-#endif
-
diff --git a/boost/tr1/tr1/bcc32/regex.h b/boost/tr1/tr1/bcc32/regex.h
deleted file mode 100644
index e3f15a5aa2..0000000000
--- a/boost/tr1/tr1/bcc32/regex.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// (C) 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)
-
-//
-// Forwarding header for Borland C++:
-//
-#if !defined(BOOST_TR1_REGEX_H_INCLUDED)
-# define BOOST_TR1_REGEX_H_INCLUDED
-# include <regex.>
-#endif
-
diff --git a/boost/tr1/tr1/bcc32/tuple.h b/boost/tr1/tr1/bcc32/tuple.h
deleted file mode 100644
index eac88089b6..0000000000
--- a/boost/tr1/tr1/bcc32/tuple.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// (C) 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)
-
-//
-// Forwarding header for Borland C++:
-//
-#if !defined(BOOST_TR1_TUPLE_H_INCLUDED)
-# define BOOST_TR1_TUPLE_H_INCLUDED
-# include <tuple.>
-#endif
-
diff --git a/boost/tr1/tr1/bcc32/type_tra.h b/boost/tr1/tr1/bcc32/type_tra.h
deleted file mode 100644
index d6fcc2ecf7..0000000000
--- a/boost/tr1/tr1/bcc32/type_tra.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// (C) 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)
-
-//
-// Forwarding header for Borland C++:
-//
-#if !defined(BOOST_TR1_TYPE_TRAITS_H_INCLUDED)
-# define BOOST_TR1_TYPE_TRAITS_H_INCLUDED
-# include <type_traits.>
-#endif
-
diff --git a/boost/tr1/tr1/bcc32/unordere.h b/boost/tr1/tr1/bcc32/unordere.h
deleted file mode 100644
index 04f88b2667..0000000000
--- a/boost/tr1/tr1/bcc32/unordere.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// (C) Copyright John Maddock 2008.
-// 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)
-
-//
-// Forwarding header for Borland C++:
-//
-#if !defined(BOOST_TR1_UNORDERED_H_INCLUDED)
-# define BOOST_TR1_UNORDERED_H_INCLUDED
-# include <unordered_set.>
-# include <unordered_map.>
-#endif
-
-
diff --git a/boost/tr1/tr1/bitset b/boost/tr1/tr1/bitset
deleted file mode 100644
index 6bc86f6800..0000000000
--- a/boost/tr1/tr1/bitset
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_bitset_INCLUDED
-# define BOOST_TR1_bitset_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_bitset_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <bitset>
-# else
-# include BOOST_TR1_STD_HEADER(bitset)
-# endif
-# ifdef BOOST_TR1_NO_bitset_RECURSION
-# undef BOOST_TR1_NO_bitset_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/cmath b/boost/tr1/tr1/cmath
deleted file mode 100644
index 649513e926..0000000000
--- a/boost/tr1/tr1/cmath
+++ /dev/null
@@ -1,41 +0,0 @@
-// (C) Copyright John Maddock 2008.
-// 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)
-
-
-#if !defined(BOOST_TR1_CMATH_INCLUDED) || defined(BOOST_TR1_NO_RECURSION)
-#ifndef BOOST_TR1_CMATH_INCLUDED
-# define BOOST_TR1_CMATH_INCLUDED
-#endif
-# ifdef BOOST_TR1_NO_CMATH_RECURSION2
-# define BOOST_TR1_NO_CMATH_RECURSION3
-# elif defined(BOOST_TR1_NO_CMATH_RECURSION)
-# define BOOST_TR1_NO_CMATH_RECURSION2
-# elif !defined(BOOST_TR1_NO_RECURSION)
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_CMATH_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <cmath>
-# else
-# include BOOST_TR1_STD_CHEADER(cmath)
-# endif
-#ifdef BOOST_TR1_NO_CMATH_RECURSION3
-# undef BOOST_TR1_NO_CMATH_RECURSION3
-#elif defined(BOOST_TR1_NO_CMATH_RECURSION2)
-# undef BOOST_TR1_NO_CMATH_RECURSION2
-#elif defined(BOOST_TR1_NO_CMATH_RECURSION)
-# undef BOOST_TR1_NO_RECURSION
-# undef BOOST_TR1_NO_CMATH_RECURSION
-# endif
-#endif
-
-#if !defined(BOOST_TR1_FULL_CMATH_INCLUDED) && !defined(BOOST_TR1_NO_RECURSION)
-# define BOOST_TR1_FULL_CMATH_INCLUDED
-# define BOOST_TR1_NO_RECURSION
-# include <boost/tr1/cmath.hpp>
-# undef BOOST_TR1_NO_RECURSION
-#endif
-
diff --git a/boost/tr1/tr1/complex b/boost/tr1/tr1/complex
deleted file mode 100644
index 81b455571b..0000000000
--- a/boost/tr1/tr1/complex
+++ /dev/null
@@ -1,31 +0,0 @@
-// (C) 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)
-
-
-#ifndef BOOST_TR1_COMPLEX_INCLUDED
-# define BOOST_TR1_COMPLEX_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_COMPLEX_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <complex>
-# else
-# include BOOST_TR1_STD_HEADER(complex)
-# endif
-# ifdef BOOST_TR1_NO_COMPLEX_RECURSION
-# undef BOOST_TR1_NO_COMPLEX_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
-#if !defined(BOOST_TR1_FULL_COMPLEX_INCLUDED) && !defined(BOOST_TR1_NO_RECURSION)
-# define BOOST_TR1_FULL_COMPLEX_INCLUDED
-# define BOOST_TR1_NO_RECURSION
-# include <boost/tr1/complex.hpp>
-# undef BOOST_TR1_NO_RECURSION
-#endif
-
diff --git a/boost/tr1/tr1/deque b/boost/tr1/tr1/deque
deleted file mode 100644
index 4e994d481f..0000000000
--- a/boost/tr1/tr1/deque
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_deque_INCLUDED
-# define BOOST_TR1_deque_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_deque_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <deque>
-# else
-# include BOOST_TR1_STD_HEADER(deque)
-# endif
-# ifdef BOOST_TR1_NO_deque_RECURSION
-# undef BOOST_TR1_NO_deque_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/exception b/boost/tr1/tr1/exception
deleted file mode 100644
index 282478a50e..0000000000
--- a/boost/tr1/tr1/exception
+++ /dev/null
@@ -1,39 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-// Important: there are no include guards on this header for Borland C++
-// The Borland version of <exception> has some peculiar circular dependencies
-// that requires multiple inclusion. Likewise for gcc (gcc-2.95.3 fix).
-//
-#ifdef BOOST_TR1_NO_exception_RECURSION2
-# define BOOST_TR1_NO_exception_RECURSION3
-#elif defined(BOOST_TR1_NO_exception_RECURSION)
-# define BOOST_TR1_NO_exception_RECURSION2
-#elif !defined(BOOST_TR1_NO_RECURSION)
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_exception_RECURSION
-#endif
-
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <exception>
-# else
-# include BOOST_TR1_STD_HEADER(exception)
-# endif
-
-#ifdef BOOST_TR1_NO_exception_RECURSION3
-# undef BOOST_TR1_NO_exception_RECURSION3
-#elif defined(BOOST_TR1_NO_exception_RECURSION2)
-# undef BOOST_TR1_NO_exception_RECURSION2
-#elif defined(BOOST_TR1_NO_exception_RECURSION)
-# undef BOOST_TR1_NO_exception_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-#endif
-
-
diff --git a/boost/tr1/tr1/fstream b/boost/tr1/tr1/fstream
deleted file mode 100644
index c44105b573..0000000000
--- a/boost/tr1/tr1/fstream
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_fstream_INCLUDED
-# define BOOST_TR1_fstream_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_fstream_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <fstream>
-# else
-# include BOOST_TR1_STD_HEADER(fstream)
-# endif
-# ifdef BOOST_TR1_NO_fstream_RECURSION
-# undef BOOST_TR1_NO_fstream_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/functional b/boost/tr1/tr1/functional
deleted file mode 100644
index e8f17338a4..0000000000
--- a/boost/tr1/tr1/functional
+++ /dev/null
@@ -1,30 +0,0 @@
-// (C) 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)
-
-#if !defined(BOOST_TR1_FUNCTIONAL_INCLUDED)
-# define BOOST_TR1_FUNCTIONAL_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_FUNCTIONAL_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <functional>
-# else
-# include BOOST_TR1_STD_HEADER(functional)
-# endif
-# ifdef BOOST_TR1_NO_FUNCTIONAL_RECURSION
-# undef BOOST_TR1_NO_FUNCTIONAL_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
-#if !defined(BOOST_TR1_FULL_FUNCTIONAL_INCLUDED) && !defined(BOOST_TR1_NO_RECURSION)
-# define BOOST_TR1_FULL_FUNCTIONAL_INCLUDED
-# define BOOST_TR1_NO_RECURSION
-# include <boost/tr1/functional.hpp>
-# undef BOOST_TR1_NO_RECURSION
-#endif
-
diff --git a/boost/tr1/tr1/iomanip b/boost/tr1/tr1/iomanip
deleted file mode 100644
index d69647c3ea..0000000000
--- a/boost/tr1/tr1/iomanip
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_iomanip_INCLUDED
-# define BOOST_TR1_iomanip_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_iomanip_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <iomanip>
-# else
-# include BOOST_TR1_STD_HEADER(iomanip)
-# endif
-# ifdef BOOST_TR1_NO_iomanip_RECURSION
-# undef BOOST_TR1_NO_iomanip_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/ios b/boost/tr1/tr1/ios
deleted file mode 100644
index 84dc321698..0000000000
--- a/boost/tr1/tr1/ios
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_ios_INCLUDED
-# define BOOST_TR1_ios_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_ios_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <ios>
-# else
-# include BOOST_TR1_STD_HEADER(ios)
-# endif
-# ifdef BOOST_TR1_NO_ios_RECURSION
-# undef BOOST_TR1_NO_ios_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/iostream b/boost/tr1/tr1/iostream
deleted file mode 100644
index bb8e7d5f89..0000000000
--- a/boost/tr1/tr1/iostream
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_iostream_INCLUDED
-# define BOOST_TR1_iostream_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_iostream_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <iostream>
-# else
-# include BOOST_TR1_STD_HEADER(iostream)
-# endif
-# ifdef BOOST_TR1_NO_iostream_RECURSION
-# undef BOOST_TR1_NO_iostream_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/istream b/boost/tr1/tr1/istream
deleted file mode 100644
index b5ab5699c5..0000000000
--- a/boost/tr1/tr1/istream
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_istream_INCLUDED
-# define BOOST_TR1_istream_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_istream_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <istream>
-# else
-# include BOOST_TR1_STD_HEADER(istream)
-# endif
-# ifdef BOOST_TR1_NO_istream_RECURSION
-# undef BOOST_TR1_NO_istream_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/iterator b/boost/tr1/tr1/iterator
deleted file mode 100644
index 0d6a5e216e..0000000000
--- a/boost/tr1/tr1/iterator
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_iterator_INCLUDED
-# define BOOST_TR1_iterator_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_iterator_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <iterator>
-# else
-# include BOOST_TR1_STD_HEADER(iterator)
-# endif
-# ifdef BOOST_TR1_NO_iterator_RECURSION
-# undef BOOST_TR1_NO_iterator_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/limits b/boost/tr1/tr1/limits
deleted file mode 100644
index 031d1937d8..0000000000
--- a/boost/tr1/tr1/limits
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_limits_INCLUDED
-# define BOOST_TR1_limits_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_limits_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <limits>
-# else
-# include BOOST_TR1_STD_HEADER(limits)
-# endif
-# ifdef BOOST_TR1_NO_limits_RECURSION
-# undef BOOST_TR1_NO_limits_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/list b/boost/tr1/tr1/list
deleted file mode 100644
index 90ea858ffc..0000000000
--- a/boost/tr1/tr1/list
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_list_INCLUDED
-# define BOOST_TR1_list_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_list_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <list>
-# else
-# include BOOST_TR1_STD_HEADER(list)
-# endif
-# ifdef BOOST_TR1_NO_list_RECURSION
-# undef BOOST_TR1_NO_list_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/locale b/boost/tr1/tr1/locale
deleted file mode 100644
index eec5b3bc3a..0000000000
--- a/boost/tr1/tr1/locale
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_locale_INCLUDED
-# define BOOST_TR1_locale_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_locale_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <locale>
-# else
-# include BOOST_TR1_STD_HEADER(locale)
-# endif
-# ifdef BOOST_TR1_NO_locale_RECURSION
-# undef BOOST_TR1_NO_locale_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/map b/boost/tr1/tr1/map
deleted file mode 100644
index 17c1ddd1ad..0000000000
--- a/boost/tr1/tr1/map
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_map_INCLUDED
-# define BOOST_TR1_map_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_map_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <map>
-# else
-# include BOOST_TR1_STD_HEADER(map)
-# endif
-# ifdef BOOST_TR1_NO_map_RECURSION
-# undef BOOST_TR1_NO_map_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/memory b/boost/tr1/tr1/memory
deleted file mode 100644
index 28fee7546a..0000000000
--- a/boost/tr1/tr1/memory
+++ /dev/null
@@ -1,31 +0,0 @@
-// (C) 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)
-
-
-#ifndef BOOST_TR1_MEMORY_INCLUDED
-# define BOOST_TR1_MEMORY_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_MEMORY_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <memory>
-# else
-# include BOOST_TR1_STD_HEADER(memory)
-# endif
-# ifdef BOOST_TR1_NO_MEMORY_RECURSION
-# undef BOOST_TR1_NO_MEMORY_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
-#if !defined(BOOST_TR1_FULL_MEMORY_INCLUDED) && !defined(BOOST_TR1_NO_RECURSION)
-# define BOOST_TR1_FULL_MEMORY_INCLUDED
-# define BOOST_TR1_NO_RECURSION
-# include <boost/tr1/memory.hpp>
-# undef BOOST_TR1_NO_RECURSION
-#endif
-
diff --git a/boost/tr1/tr1/new b/boost/tr1/tr1/new
deleted file mode 100644
index 91d7157253..0000000000
--- a/boost/tr1/tr1/new
+++ /dev/null
@@ -1,35 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifdef BOOST_TR1_NO_new_RECURSION2
-# define BOOST_TR1_NO_new_RECURSION3
-#elif defined(BOOST_TR1_NO_new_RECURSION)
-# define BOOST_TR1_NO_new_RECURSION2
-#elif !defined(BOOST_TR1_NO_RECURSION)
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_new_RECURSION
-#endif
-
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <new>
-# else
-# include BOOST_TR1_STD_HEADER(new)
-# endif
-
-#ifdef BOOST_TR1_NO_new_RECURSION3
-# undef BOOST_TR1_NO_new_RECURSION3
-#elif defined(BOOST_TR1_NO_new_RECURSION2)
-# undef BOOST_TR1_NO_new_RECURSION2
-#elif defined(BOOST_TR1_NO_new_RECURSION)
-# undef BOOST_TR1_NO_new_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-#endif
-
-
diff --git a/boost/tr1/tr1/numeric b/boost/tr1/tr1/numeric
deleted file mode 100644
index afa82e134f..0000000000
--- a/boost/tr1/tr1/numeric
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_numeric_INCLUDED
-# define BOOST_TR1_numeric_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_numeric_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <numeric>
-# else
-# include BOOST_TR1_STD_HEADER(numeric)
-# endif
-# ifdef BOOST_TR1_NO_numeric_RECURSION
-# undef BOOST_TR1_NO_numeric_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/ostream b/boost/tr1/tr1/ostream
deleted file mode 100644
index 5b924d6d85..0000000000
--- a/boost/tr1/tr1/ostream
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_ostream_INCLUDED
-# define BOOST_TR1_ostream_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_ostream_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <ostream>
-# else
-# include BOOST_TR1_STD_HEADER(ostream)
-# endif
-# ifdef BOOST_TR1_NO_ostream_RECURSION
-# undef BOOST_TR1_NO_ostream_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/queue b/boost/tr1/tr1/queue
deleted file mode 100644
index 91311f1231..0000000000
--- a/boost/tr1/tr1/queue
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_queue_INCLUDED
-# define BOOST_TR1_queue_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_queue_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <queue>
-# else
-# include BOOST_TR1_STD_HEADER(queue)
-# endif
-# ifdef BOOST_TR1_NO_queue_RECURSION
-# undef BOOST_TR1_NO_queue_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/random b/boost/tr1/tr1/random
deleted file mode 100644
index 623c35c650..0000000000
--- a/boost/tr1/tr1/random
+++ /dev/null
@@ -1,34 +0,0 @@
-// (C) 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)
-
-
-#ifndef BOOST_TR1_RANDOM_INCLUDED
-# define BOOST_TR1_RANDOM_INCLUDED
-# include <boost/tr1/detail/config_all.hpp>
-
-# ifdef BOOST_HAS_CPP_0X
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <random>
-# else
-# include BOOST_TR1_STD_HEADER(random)
-# endif
-# endif
-
-# if !defined(BOOST_TR1_NO_RECURSION)
-# define BOOST_TR1_NO_RECURSION
-# ifdef BOOST_HAS_TR1_RANDOM
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next BOOST_TR1_HEADER(random)
-# else
-# include BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(random))
-# endif
-# else
-# include <boost/tr1/random.hpp>
-# endif
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
-
diff --git a/boost/tr1/tr1/regex b/boost/tr1/tr1/regex
deleted file mode 100644
index a97de93b62..0000000000
--- a/boost/tr1/tr1/regex
+++ /dev/null
@@ -1,22 +0,0 @@
-// (C) 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)
-
-
-#ifndef BOOST_TR1_REGEX_INCLUDED
-# define BOOST_TR1_REGEX_INCLUDED
-# define BOOST_TR1_NO_RECURSION
-# include <boost/tr1/detail/config_all.hpp>
-# ifdef BOOST_HAS_TR1_REGEX
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next BOOST_TR1_HEADER(regex)
-# else
-# include BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(regex))
-# endif
-# else
-# include <boost/tr1/regex.hpp>
-# endif
-# undef BOOST_TR1_NO_RECURSION
-#endif
-
diff --git a/boost/tr1/tr1/set b/boost/tr1/tr1/set
deleted file mode 100644
index 52d374c344..0000000000
--- a/boost/tr1/tr1/set
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_set_INCLUDED
-# define BOOST_TR1_set_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_set_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <set>
-# else
-# include BOOST_TR1_STD_HEADER(set)
-# endif
-# ifdef BOOST_TR1_NO_set_RECURSION
-# undef BOOST_TR1_NO_set_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/sstream b/boost/tr1/tr1/sstream
deleted file mode 100644
index a5e9c53ff9..0000000000
--- a/boost/tr1/tr1/sstream
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_sstream_INCLUDED
-# define BOOST_TR1_sstream_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_sstream_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <sstream>
-# else
-# include BOOST_TR1_STD_HEADER(sstream)
-# endif
-# ifdef BOOST_TR1_NO_sstream_RECURSION
-# undef BOOST_TR1_NO_sstream_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/stack b/boost/tr1/tr1/stack
deleted file mode 100644
index b23b7ee54c..0000000000
--- a/boost/tr1/tr1/stack
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_stack_INCLUDED
-# define BOOST_TR1_stack_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_stack_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <stack>
-# else
-# include BOOST_TR1_STD_HEADER(stack)
-# endif
-# ifdef BOOST_TR1_NO_stack_RECURSION
-# undef BOOST_TR1_NO_stack_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/stdexcept b/boost/tr1/tr1/stdexcept
deleted file mode 100644
index 1d3cd2a780..0000000000
--- a/boost/tr1/tr1/stdexcept
+++ /dev/null
@@ -1,34 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifdef BOOST_TR1_NO_stdexcept_RECURSION2
-# define BOOST_TR1_NO_stdexcept_RECURSION3
-#elif defined(BOOST_TR1_NO_stdexcept_RECURSION)
-# define BOOST_TR1_NO_stdexcept_RECURSION2
-#elif !defined(BOOST_TR1_NO_RECURSION)
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_stdexcept_RECURSION
-#endif
-
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <stdexcept>
-# else
-# include BOOST_TR1_STD_HEADER(stdexcept)
-# endif
-
-#ifdef BOOST_TR1_NO_stdexcept_RECURSION3
-# undef BOOST_TR1_NO_stdexcept_RECURSION3
-#elif defined(BOOST_TR1_NO_stdexcept_RECURSION2)
-# undef BOOST_TR1_NO_stdexcept_RECURSION2
-#elif defined(BOOST_TR1_NO_stdexcept_RECURSION)
-# undef BOOST_TR1_NO_stdexcept_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-#endif
-
diff --git a/boost/tr1/tr1/streambuf b/boost/tr1/tr1/streambuf
deleted file mode 100644
index 99208ec66c..0000000000
--- a/boost/tr1/tr1/streambuf
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_streambuf_INCLUDED
-# define BOOST_TR1_streambuf_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_streambuf_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <streambuf>
-# else
-# include BOOST_TR1_STD_HEADER(streambuf)
-# endif
-# ifdef BOOST_TR1_NO_streambuf_RECURSION
-# undef BOOST_TR1_NO_streambuf_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/string b/boost/tr1/tr1/string
deleted file mode 100644
index a59e00b15b..0000000000
--- a/boost/tr1/tr1/string
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_string_INCLUDED
-# define BOOST_TR1_string_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_string_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <string>
-# else
-# include BOOST_TR1_STD_HEADER(string)
-# endif
-# ifdef BOOST_TR1_NO_string_RECURSION
-# undef BOOST_TR1_NO_string_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/strstream b/boost/tr1/tr1/strstream
deleted file mode 100644
index a15018074c..0000000000
--- a/boost/tr1/tr1/strstream
+++ /dev/null
@@ -1,29 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_strstream_INCLUDED
-# define BOOST_TR1_strstream_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_strstream_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <strstream>
-# elif defined(__GNUC__) && (__GNUC__ >= 4) && defined(__GLIBCXX__) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
-# include <backward/strstream>
-# else
-# include BOOST_TR1_STD_HEADER(strstream)
-# endif
-# ifdef BOOST_TR1_NO_strstream_RECURSION
-# undef BOOST_TR1_NO_strstream_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/sun/algorithm.SUNWCCh b/boost/tr1/tr1/sun/algorithm.SUNWCCh
deleted file mode 100644
index d4e9be5476..0000000000
--- a/boost/tr1/tr1/sun/algorithm.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../algorithm"
-
diff --git a/boost/tr1/tr1/sun/array.SUNWCCh b/boost/tr1/tr1/sun/array.SUNWCCh
deleted file mode 100644
index 580fc874d0..0000000000
--- a/boost/tr1/tr1/sun/array.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../array"
-
diff --git a/boost/tr1/tr1/sun/bcc32.SUNWCCh b/boost/tr1/tr1/sun/bcc32.SUNWCCh
deleted file mode 100644
index 1df698ecc6..0000000000
--- a/boost/tr1/tr1/sun/bcc32.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../bcc32"
-
diff --git a/boost/tr1/tr1/sun/bitset.SUNWCCh b/boost/tr1/tr1/sun/bitset.SUNWCCh
deleted file mode 100644
index 9768a40675..0000000000
--- a/boost/tr1/tr1/sun/bitset.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../bitset"
-
diff --git a/boost/tr1/tr1/sun/cmath.SUNWCCh b/boost/tr1/tr1/sun/cmath.SUNWCCh
deleted file mode 100644
index 0d543eeadb..0000000000
--- a/boost/tr1/tr1/sun/cmath.SUNWCCh
+++ /dev/null
@@ -1,7 +0,0 @@
-// (C) Copyright John Maddock 2008.
-// 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 "../cmath"
-
-
diff --git a/boost/tr1/tr1/sun/complex.SUNWCCh b/boost/tr1/tr1/sun/complex.SUNWCCh
deleted file mode 100644
index 7694f6255c..0000000000
--- a/boost/tr1/tr1/sun/complex.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../complex"
-
diff --git a/boost/tr1/tr1/sun/deque.SUNWCCh b/boost/tr1/tr1/sun/deque.SUNWCCh
deleted file mode 100644
index 55b8ba03f0..0000000000
--- a/boost/tr1/tr1/sun/deque.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../deque"
-
diff --git a/boost/tr1/tr1/sun/exception.SUNWCCh b/boost/tr1/tr1/sun/exception.SUNWCCh
deleted file mode 100644
index 32bd2aac00..0000000000
--- a/boost/tr1/tr1/sun/exception.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../exception"
-
diff --git a/boost/tr1/tr1/sun/fstream.SUNWCCh b/boost/tr1/tr1/sun/fstream.SUNWCCh
deleted file mode 100644
index 5838672b06..0000000000
--- a/boost/tr1/tr1/sun/fstream.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../fstream"
-
diff --git a/boost/tr1/tr1/sun/functional.SUNWCCh b/boost/tr1/tr1/sun/functional.SUNWCCh
deleted file mode 100644
index ff40942138..0000000000
--- a/boost/tr1/tr1/sun/functional.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../functional"
-
diff --git a/boost/tr1/tr1/sun/iomanip.SUNWCCh b/boost/tr1/tr1/sun/iomanip.SUNWCCh
deleted file mode 100644
index fb7d563d1d..0000000000
--- a/boost/tr1/tr1/sun/iomanip.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../iomanip"
-
diff --git a/boost/tr1/tr1/sun/ios.SUNWCCh b/boost/tr1/tr1/sun/ios.SUNWCCh
deleted file mode 100644
index a41a90039d..0000000000
--- a/boost/tr1/tr1/sun/ios.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../ios"
-
diff --git a/boost/tr1/tr1/sun/iostream.SUNWCCh b/boost/tr1/tr1/sun/iostream.SUNWCCh
deleted file mode 100644
index 0b121dd942..0000000000
--- a/boost/tr1/tr1/sun/iostream.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../iostream"
-
diff --git a/boost/tr1/tr1/sun/istream.SUNWCCh b/boost/tr1/tr1/sun/istream.SUNWCCh
deleted file mode 100644
index 75bf29109d..0000000000
--- a/boost/tr1/tr1/sun/istream.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../istream"
-
diff --git a/boost/tr1/tr1/sun/iterator.SUNWCCh b/boost/tr1/tr1/sun/iterator.SUNWCCh
deleted file mode 100644
index 1f253ab7d8..0000000000
--- a/boost/tr1/tr1/sun/iterator.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../iterator"
-
diff --git a/boost/tr1/tr1/sun/limits.SUNWCCh b/boost/tr1/tr1/sun/limits.SUNWCCh
deleted file mode 100644
index 47017e78ac..0000000000
--- a/boost/tr1/tr1/sun/limits.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../limits"
-
diff --git a/boost/tr1/tr1/sun/list.SUNWCCh b/boost/tr1/tr1/sun/list.SUNWCCh
deleted file mode 100644
index 14b862dffa..0000000000
--- a/boost/tr1/tr1/sun/list.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../list"
-
diff --git a/boost/tr1/tr1/sun/locale.SUNWCCh b/boost/tr1/tr1/sun/locale.SUNWCCh
deleted file mode 100644
index 30b19a9c73..0000000000
--- a/boost/tr1/tr1/sun/locale.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../locale"
-
diff --git a/boost/tr1/tr1/sun/map.SUNWCCh b/boost/tr1/tr1/sun/map.SUNWCCh
deleted file mode 100644
index b9d954fd3f..0000000000
--- a/boost/tr1/tr1/sun/map.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../map"
-
diff --git a/boost/tr1/tr1/sun/memory.SUNWCCh b/boost/tr1/tr1/sun/memory.SUNWCCh
deleted file mode 100644
index fdde926994..0000000000
--- a/boost/tr1/tr1/sun/memory.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../memory"
-
diff --git a/boost/tr1/tr1/sun/new.SUNWCCh b/boost/tr1/tr1/sun/new.SUNWCCh
deleted file mode 100644
index e90b0ab74e..0000000000
--- a/boost/tr1/tr1/sun/new.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../new"
-
diff --git a/boost/tr1/tr1/sun/numeric.SUNWCCh b/boost/tr1/tr1/sun/numeric.SUNWCCh
deleted file mode 100644
index ad91add454..0000000000
--- a/boost/tr1/tr1/sun/numeric.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../numeric"
-
diff --git a/boost/tr1/tr1/sun/ostream.SUNWCCh b/boost/tr1/tr1/sun/ostream.SUNWCCh
deleted file mode 100644
index f579d6eaf1..0000000000
--- a/boost/tr1/tr1/sun/ostream.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../ostream"
-
diff --git a/boost/tr1/tr1/sun/queue.SUNWCCh b/boost/tr1/tr1/sun/queue.SUNWCCh
deleted file mode 100644
index ace2924182..0000000000
--- a/boost/tr1/tr1/sun/queue.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../queue"
-
diff --git a/boost/tr1/tr1/sun/random.SUNWCCh b/boost/tr1/tr1/sun/random.SUNWCCh
deleted file mode 100644
index 1a9460d5d7..0000000000
--- a/boost/tr1/tr1/sun/random.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../random"
-
diff --git a/boost/tr1/tr1/sun/regex.SUNWCCh b/boost/tr1/tr1/sun/regex.SUNWCCh
deleted file mode 100644
index 8a5ee4bc02..0000000000
--- a/boost/tr1/tr1/sun/regex.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../regex"
-
diff --git a/boost/tr1/tr1/sun/set.SUNWCCh b/boost/tr1/tr1/sun/set.SUNWCCh
deleted file mode 100644
index 0daa557872..0000000000
--- a/boost/tr1/tr1/sun/set.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../set"
-
diff --git a/boost/tr1/tr1/sun/sstream.SUNWCCh b/boost/tr1/tr1/sun/sstream.SUNWCCh
deleted file mode 100644
index 37e3d09756..0000000000
--- a/boost/tr1/tr1/sun/sstream.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../sstream"
-
diff --git a/boost/tr1/tr1/sun/stack.SUNWCCh b/boost/tr1/tr1/sun/stack.SUNWCCh
deleted file mode 100644
index d05ce63c56..0000000000
--- a/boost/tr1/tr1/sun/stack.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../stack"
-
diff --git a/boost/tr1/tr1/sun/stdexcept.SUNWCCh b/boost/tr1/tr1/sun/stdexcept.SUNWCCh
deleted file mode 100644
index 9405ab8d1c..0000000000
--- a/boost/tr1/tr1/sun/stdexcept.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../stdexcept"
-
diff --git a/boost/tr1/tr1/sun/streambuf.SUNWCCh b/boost/tr1/tr1/sun/streambuf.SUNWCCh
deleted file mode 100644
index 23120869fc..0000000000
--- a/boost/tr1/tr1/sun/streambuf.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../streambuf"
-
diff --git a/boost/tr1/tr1/sun/string.SUNWCCh b/boost/tr1/tr1/sun/string.SUNWCCh
deleted file mode 100644
index 7fcb2a1ab6..0000000000
--- a/boost/tr1/tr1/sun/string.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../string"
-
diff --git a/boost/tr1/tr1/sun/strstream.SUNWCCh b/boost/tr1/tr1/sun/strstream.SUNWCCh
deleted file mode 100644
index 8e0b0e53ee..0000000000
--- a/boost/tr1/tr1/sun/strstream.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../strstream"
-
diff --git a/boost/tr1/tr1/sun/sun.SUNWCCh b/boost/tr1/tr1/sun/sun.SUNWCCh
deleted file mode 100644
index 5fc9b461aa..0000000000
--- a/boost/tr1/tr1/sun/sun.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../sun"
-
diff --git a/boost/tr1/tr1/sun/tuple.SUNWCCh b/boost/tr1/tr1/sun/tuple.SUNWCCh
deleted file mode 100644
index f20bff85d4..0000000000
--- a/boost/tr1/tr1/sun/tuple.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../tuple"
-
diff --git a/boost/tr1/tr1/sun/type_traits.SUNWCCh b/boost/tr1/tr1/sun/type_traits.SUNWCCh
deleted file mode 100644
index 0c93c9bf90..0000000000
--- a/boost/tr1/tr1/sun/type_traits.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../type_traits"
-
diff --git a/boost/tr1/tr1/sun/typeinfo.SUNWCCh b/boost/tr1/tr1/sun/typeinfo.SUNWCCh
deleted file mode 100644
index a583b1106f..0000000000
--- a/boost/tr1/tr1/sun/typeinfo.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../typeinfo"
-
diff --git a/boost/tr1/tr1/sun/unordered_map.SUNWCCh b/boost/tr1/tr1/sun/unordered_map.SUNWCCh
deleted file mode 100644
index 2c7e2c5edb..0000000000
--- a/boost/tr1/tr1/sun/unordered_map.SUNWCCh
+++ /dev/null
@@ -1,7 +0,0 @@
-// (C) Copyright John Maddock 2008.
-// 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 "../unordered_map"
-
-
diff --git a/boost/tr1/tr1/sun/unordered_set.SUNWCCh b/boost/tr1/tr1/sun/unordered_set.SUNWCCh
deleted file mode 100644
index 119058bb78..0000000000
--- a/boost/tr1/tr1/sun/unordered_set.SUNWCCh
+++ /dev/null
@@ -1,7 +0,0 @@
-// (C) Copyright John Maddock 2008.
-// 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 "../unordered_set"
-
-
diff --git a/boost/tr1/tr1/sun/utility.SUNWCCh b/boost/tr1/tr1/sun/utility.SUNWCCh
deleted file mode 100644
index 7cbc6e25a5..0000000000
--- a/boost/tr1/tr1/sun/utility.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../utility"
-
diff --git a/boost/tr1/tr1/sun/valarray.SUNWCCh b/boost/tr1/tr1/sun/valarray.SUNWCCh
deleted file mode 100644
index 266caf2d73..0000000000
--- a/boost/tr1/tr1/sun/valarray.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../valarray"
-
diff --git a/boost/tr1/tr1/sun/vector.SUNWCCh b/boost/tr1/tr1/sun/vector.SUNWCCh
deleted file mode 100644
index 0e2fc7ffcd..0000000000
--- a/boost/tr1/tr1/sun/vector.SUNWCCh
+++ /dev/null
@@ -1,6 +0,0 @@
-// (C) Copyright John Maddock 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)
-#include "../vector"
-
diff --git a/boost/tr1/tr1/tuple b/boost/tr1/tr1/tuple
deleted file mode 100644
index 83201c2abf..0000000000
--- a/boost/tr1/tr1/tuple
+++ /dev/null
@@ -1,34 +0,0 @@
-// (C) 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)
-
-
-#ifndef BOOST_TR1_TUPLE_INCLUDED
-# define BOOST_TR1_TUPLE_INCLUDED
-# include <boost/tr1/detail/config_all.hpp>
-
-# ifdef BOOST_HAS_CPP_0X
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <tuple>
-# else
-# include BOOST_TR1_STD_HEADER(tuple)
-# endif
-# endif
-
-# if !defined(BOOST_TR1_NO_RECURSION)
-# define BOOST_TR1_NO_RECURSION
-# ifdef BOOST_HAS_TR1_TUPLE
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next BOOST_TR1_HEADER(tuple)
-# else
-# include BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(tuple))
-# endif
-# else
-# include <boost/tr1/tuple.hpp>
-# endif
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
-
diff --git a/boost/tr1/tr1/type_traits b/boost/tr1/tr1/type_traits
deleted file mode 100644
index ef5a068683..0000000000
--- a/boost/tr1/tr1/type_traits
+++ /dev/null
@@ -1,43 +0,0 @@
-// (C) 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)
-
-
-#include <boost/tr1/detail/config_all.hpp>
-
-#if (!defined(BOOST_TR1_TYPE_TRAITS_INCLUDED) || defined(BOOST_TR1_NO_RECURSION)) && defined(BOOST_HAS_CPP_0X)
-#ifndef BOOST_TR1_TYPE_TRAITS_INCLUDED
-# define BOOST_TR1_TYPE_TRAITS_INCLUDED
-#endif
-# ifdef BOOST_TR1_NO_TYPE_TRAITS_RECURSION2
-# define BOOST_TR1_NO_TYPE_TRAITS_RECURSION3
-# elif defined(BOOST_TR1_NO_TYPE_TRAITS_RECURSION)
-# define BOOST_TR1_NO_TYPE_TRAITS_RECURSION2
-# elif !defined(BOOST_TR1_NO_RECURSION)
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_TYPE_TRAITS_RECURSION
-# endif
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <type_traits>
-# else
-# include BOOST_TR1_STD_HEADER(type_traits)
-# endif
-#ifdef BOOST_TR1_NO_TYPE_TRAITS_RECURSION3
-# undef BOOST_TR1_NO_TYPE_TRAITS_RECURSION3
-#elif defined(BOOST_TR1_NO_TYPE_TRAITS_RECURSION2)
-# undef BOOST_TR1_NO_TYPE_TRAITS_RECURSION2
-#elif defined(BOOST_TR1_NO_TYPE_TRAITS_RECURSION)
-# undef BOOST_TR1_NO_RECURSION
-# undef BOOST_TR1_NO_TYPE_TRAITS_RECURSION
-# endif
-#endif
-
-#if !defined(BOOST_TR1_FULL_TYPE_TRAITS_INCLUDED) && !defined(BOOST_TR1_NO_RECURSION)
-# define BOOST_TR1_FULL_TYPE_TRAITS_INCLUDED
-# define BOOST_TR1_NO_RECURSION
-# include <boost/tr1/type_traits.hpp>
-# undef BOOST_TR1_NO_RECURSION
-#endif
-
-
diff --git a/boost/tr1/tr1/typeinfo b/boost/tr1/tr1/typeinfo
deleted file mode 100644
index 97c0f79035..0000000000
--- a/boost/tr1/tr1/typeinfo
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_typeinfo_INCLUDED
-# define BOOST_TR1_typeinfo_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_typeinfo_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <typeinfo>
-# else
-# include BOOST_TR1_STD_HEADER(typeinfo)
-# endif
-# ifdef BOOST_TR1_NO_typeinfo_RECURSION
-# undef BOOST_TR1_NO_typeinfo_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/unordered_map b/boost/tr1/tr1/unordered_map
deleted file mode 100644
index f8984805c8..0000000000
--- a/boost/tr1/tr1/unordered_map
+++ /dev/null
@@ -1,34 +0,0 @@
-// (C) Copyright John Maddock 2008.
-// 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_TR1_UNORDERED_MAP_INCLUDED
-# define BOOST_TR1_UNORDERED_MAP_INCLUDED
-# include <boost/tr1/detail/config_all.hpp>
-
-# ifdef BOOST_HAS_CPP_0X
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <unordered_map>
-# else
-# include BOOST_TR1_STD_HEADER(unordered_map)
-# endif
-# endif
-
-# if !defined(BOOST_TR1_NO_RECURSION)
-# define BOOST_TR1_NO_RECURSION
-# ifdef BOOST_HAS_TR1_UNORDERED_MAP
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next BOOST_TR1_HEADER(unordered_map)
-# else
-# include BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(unordered_map))
-# endif
-# else
-# include <boost/tr1/unordered_map.hpp>
-# endif
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
-
diff --git a/boost/tr1/tr1/unordered_set b/boost/tr1/tr1/unordered_set
deleted file mode 100644
index 92d0c6149b..0000000000
--- a/boost/tr1/tr1/unordered_set
+++ /dev/null
@@ -1,34 +0,0 @@
-// (C) Copyright John Maddock 2008.
-// 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_TR1_UNORDERED_SET_INCLUDED
-# define BOOST_TR1_UNORDERED_SET_INCLUDED
-# include <boost/tr1/detail/config_all.hpp>
-
-# ifdef BOOST_HAS_CPP_0X
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <unordered_map>
-# else
-# include BOOST_TR1_STD_HEADER(unordered_map)
-# endif
-# endif
-
-# if !defined(BOOST_TR1_NO_RECURSION)
-# define BOOST_TR1_NO_RECURSION
-# ifdef BOOST_HAS_TR1_UNORDERED_SET
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next BOOST_TR1_HEADER(unordered_set)
-# else
-# include BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(unordered_set))
-# endif
-# else
-# include <boost/tr1/unordered_set.hpp>
-# endif
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
-
diff --git a/boost/tr1/tr1/utility b/boost/tr1/tr1/utility
deleted file mode 100644
index bb03622579..0000000000
--- a/boost/tr1/tr1/utility
+++ /dev/null
@@ -1,41 +0,0 @@
-// (C) 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)
-
-
-#if !defined(BOOST_TR1_UTILITY_INCLUDED) || defined(BOOST_TR1_NO_RECURSION)
-#ifndef BOOST_TR1_UTILITY_INCLUDED
-# define BOOST_TR1_UTILITY_INCLUDED
-#endif
-# ifdef BOOST_TR1_NO_UTILITY_RECURSION2
-# define BOOST_TR1_NO_UTILITY_RECURSION3
-# elif defined(BOOST_TR1_NO_UTILITY_RECURSION)
-# define BOOST_TR1_NO_UTILITY_RECURSION2
-# elif !defined(BOOST_TR1_NO_RECURSION)
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_UTILITY_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <utility>
-# else
-# include BOOST_TR1_STD_HEADER(utility)
-# endif
-#ifdef BOOST_TR1_NO_UTILITY_RECURSION3
-# undef BOOST_TR1_NO_UTILITY_RECURSION3
-#elif defined(BOOST_TR1_NO_UTILITY_RECURSION2)
-# undef BOOST_TR1_NO_UTILITY_RECURSION2
-#elif defined(BOOST_TR1_NO_UTILITY_RECURSION)
-# undef BOOST_TR1_NO_RECURSION
-# undef BOOST_TR1_NO_UTILITY_RECURSION
-# endif
-#endif
-
-#if !defined(BOOST_TR1_FULL_UTILITY_INCLUDED) && !defined(BOOST_TR1_NO_RECURSION)
-# define BOOST_TR1_FULL_UTILITY_INCLUDED
-# define BOOST_TR1_NO_RECURSION
-# include <boost/tr1/utility.hpp>
-# undef BOOST_TR1_NO_RECURSION
-#endif
-
diff --git a/boost/tr1/tr1/valarray b/boost/tr1/tr1/valarray
deleted file mode 100644
index 6269fcd743..0000000000
--- a/boost/tr1/tr1/valarray
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_valarray_INCLUDED
-# define BOOST_TR1_valarray_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_valarray_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <valarray>
-# else
-# include BOOST_TR1_STD_HEADER(valarray)
-# endif
-# ifdef BOOST_TR1_NO_valarray_RECURSION
-# undef BOOST_TR1_NO_valarray_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tr1/vector b/boost/tr1/tr1/vector
deleted file mode 100644
index d9e658161e..0000000000
--- a/boost/tr1/tr1/vector
+++ /dev/null
@@ -1,27 +0,0 @@
-// (C) 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)
-//
-// This file exists to prevent std lib headers from accidentally
-// including a TR1 extention header; we must suppress this otherwise
-// we can end up with cyclic dependencies with some std lib implementations.
-//
-#ifndef BOOST_TR1_vector_INCLUDED
-# define BOOST_TR1_vector_INCLUDED
-# ifndef BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_RECURSION
-# define BOOST_TR1_NO_vector_RECURSION
-# endif
-# include <boost/tr1/detail/config_all.hpp>
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next <vector>
-# else
-# include BOOST_TR1_STD_HEADER(vector)
-# endif
-# ifdef BOOST_TR1_NO_vector_RECURSION
-# undef BOOST_TR1_NO_vector_RECURSION
-# undef BOOST_TR1_NO_RECURSION
-# endif
-#endif
-
diff --git a/boost/tr1/tuple.hpp b/boost/tr1/tuple.hpp
deleted file mode 100644
index 7bc8169dda..0000000000
--- a/boost/tr1/tuple.hpp
+++ /dev/null
@@ -1,82 +0,0 @@
-// (C) 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)
-
-#ifndef BOOST_TR1_TUPLE_HPP_INCLUDED
-# define BOOST_TR1_TUPLE_HPP_INCLUDED
-# include <boost/tr1/detail/config.hpp>
-
-#ifdef BOOST_HAS_TR1_TUPLE
-
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next BOOST_TR1_HEADER(tuple)
-# else
-# include <boost/tr1/detail/config_all.hpp>
-# include BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(tuple))
-# endif
-
-#else
-
-#if defined(BOOST_TR1_USE_OLD_TUPLE)
-
-#include <boost/tuple/tuple.hpp>
-#include <boost/tuple/tuple_comparison.hpp>
-#include <boost/type_traits/integral_constant.hpp>
-
-namespace std{ namespace tr1{
-
-using ::boost::tuple;
-
-// [6.1.3.2] Tuple creation functions
-using ::boost::tuples::ignore;
-using ::boost::make_tuple;
-using ::boost::tie;
-
-// [6.1.3.3] Tuple helper classes
-template <class T>
-struct tuple_size
- : public ::boost::integral_constant
- < ::std::size_t, ::boost::tuples::length<T>::value>
-{};
-
-template < int I, class T>
-struct tuple_element
-{
- typedef typename boost::tuples::element<I,T>::type type;
-};
-
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
-// [6.1.3.4] Element access
-using ::boost::get;
-#endif
-
-} } // namespaces
-
-#else
-
-#include <boost/fusion/include/tuple.hpp>
-#include <boost/fusion/include/std_pair.hpp>
-
-namespace std{ namespace tr1{
-
-using ::boost::fusion::tuple;
-
-// [6.1.3.2] Tuple creation functions
-using ::boost::fusion::ignore;
-using ::boost::fusion::make_tuple;
-using ::boost::fusion::tie;
-using ::boost::fusion::get;
-
-// [6.1.3.3] Tuple helper classes
-using ::boost::fusion::tuple_size;
-using ::boost::fusion::tuple_element;
-
-}}
-
-#endif
-
-#endif
-
-#endif
-
diff --git a/boost/tr1/type_traits.hpp b/boost/tr1/type_traits.hpp
deleted file mode 100644
index 367ccb93e8..0000000000
--- a/boost/tr1/type_traits.hpp
+++ /dev/null
@@ -1,87 +0,0 @@
-// (C) 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)
-
-#ifndef BOOST_TR1_TYPE_TRAITS_HPP_INCLUDED
-# define BOOST_TR1_TYPE_TRAITS_HPP_INCLUDED
-# include <boost/tr1/detail/config.hpp>
-
-#ifdef BOOST_HAS_TR1_TYPE_TRAITS
-
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next BOOST_TR1_HEADER(type_traits)
-# else
-# include <boost/tr1/detail/config_all.hpp>
-# include BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(type_traits))
-# endif
-
-#else
-// Boost Type Traits:
-#include <boost/type_traits.hpp>
-#include <boost/type_traits/is_base_of_tr1.hpp>
-
-namespace std { namespace tr1{
-
- using ::boost::integral_constant;
- using ::boost::true_type;
- using ::boost::false_type;
- using ::boost::is_void;
- using ::boost::is_integral;
- using ::boost::is_floating_point;
- using ::boost::is_array;
- using ::boost::is_pointer;
- using ::boost::is_reference;
- using ::boost::is_member_object_pointer;
- using ::boost::is_member_function_pointer;
- using ::boost::is_enum;
- using ::boost::is_union;
- using ::boost::is_class;
- using ::boost::is_function;
- using ::boost::is_arithmetic;
- using ::boost::is_fundamental;
- using ::boost::is_object;
- using ::boost::is_scalar;
- using ::boost::is_compound;
- using ::boost::is_member_pointer;
- using ::boost::is_const;
- using ::boost::is_volatile;
- using ::boost::is_pod;
- using ::boost::is_empty;
- using ::boost::is_polymorphic;
- using ::boost::is_abstract;
- using ::boost::has_trivial_constructor;
- using ::boost::has_trivial_copy;
- using ::boost::has_trivial_assign;
- using ::boost::has_trivial_destructor;
- using ::boost::has_nothrow_constructor;
- using ::boost::has_nothrow_copy;
- using ::boost::has_nothrow_assign;
- using ::boost::has_virtual_destructor;
- using ::boost::is_signed;
- using ::boost::is_unsigned;
- using ::boost::alignment_of;
- using ::boost::rank;
- using ::boost::extent;
- using ::boost::is_same;
- using ::boost::tr1::is_base_of;
- using ::boost::is_convertible;
- using ::boost::remove_const;
- using ::boost::remove_volatile;
- using ::boost::remove_cv;
- using ::boost::add_const;
- using ::boost::add_volatile;
- using ::boost::add_cv;
- using ::boost::remove_reference;
- using ::boost::add_reference;
- using ::boost::remove_extent;
- using ::boost::remove_all_extents;
- using ::boost::remove_pointer;
- using ::boost::add_pointer;
- using ::boost::aligned_storage;
-
-} }
-
-#endif
-
-#endif
diff --git a/boost/tr1/unordered_map.hpp b/boost/tr1/unordered_map.hpp
deleted file mode 100644
index 39c773ba6e..0000000000
--- a/boost/tr1/unordered_map.hpp
+++ /dev/null
@@ -1,33 +0,0 @@
-// (C) Copyright John Maddock 2008.
-// 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_TR1_UNORDERED_MAP_HPP_INCLUDED
-# define BOOST_TR1_UNORDERED_MAP_HPP_INCLUDED
-# include <boost/tr1/detail/config.hpp>
-
-#ifdef BOOST_HAS_TR1_UNORDERED_MAP
-
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next BOOST_TR1_HEADER(unordered_map)
-# else
-# include <boost/tr1/detail/config_all.hpp>
-# include BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(unordered_map))
-# endif
-
-#else
-
-#include <boost/unordered_map.hpp>
-
-namespace std{ namespace tr1{
-
- using ::boost::unordered_map;
- using ::boost::unordered_multimap;
- using ::boost::swap;
-
-} } // namespaces
-
-#endif
-
-#endif
diff --git a/boost/tr1/unordered_set.hpp b/boost/tr1/unordered_set.hpp
deleted file mode 100644
index 7410b66ca1..0000000000
--- a/boost/tr1/unordered_set.hpp
+++ /dev/null
@@ -1,33 +0,0 @@
-// (C) Copyright John Maddock 2008.
-// 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_TR1_UNORDERED_SET_HPP_INCLUDED
-# define BOOST_TR1_UNORDERED_SET_HPP_INCLUDED
-# include <boost/tr1/detail/config.hpp>
-
-#ifdef BOOST_HAS_TR1_UNORDERED_SET
-
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next BOOST_TR1_HEADER(unordered_set)
-# else
-# include <boost/tr1/detail/config_all.hpp>
-# include BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(unordered_set))
-# endif
-
-#else
-
-#include <boost/unordered_set.hpp>
-
-namespace std{ namespace tr1{
-
- using ::boost::unordered_set;
- using ::boost::unordered_multiset;
- using ::boost::swap;
-
-} } // namespaces
-
-#endif
-
-#endif
diff --git a/boost/tr1/utility.hpp b/boost/tr1/utility.hpp
deleted file mode 100644
index 0310b5ce41..0000000000
--- a/boost/tr1/utility.hpp
+++ /dev/null
@@ -1,121 +0,0 @@
-// (C) 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)
-
-#ifndef BOOST_TR1_UTILITY_HPP_INCLUDED
-# define BOOST_TR1_UTILITY_HPP_INCLUDED
-# include <boost/tr1/detail/config.hpp>
-
-#ifdef BOOST_HAS_TR1_UTILITY
-
-# if defined(BOOST_HAS_INCLUDE_NEXT) && !defined(BOOST_TR1_DISABLE_INCLUDE_NEXT)
-# include_next BOOST_TR1_HEADER(utility)
-# else
-# include <boost/tr1/detail/config_all.hpp>
-# include BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(utility))
-# endif
-
-#else
-
-#if defined(BOOST_TR1_USE_OLD_TUPLE)
-
-#include <boost/type_traits/integral_constant.hpp>
-#include <boost/type_traits/add_const.hpp>
-#include <boost/type_traits/add_reference.hpp>
-#include <boost/mpl/if.hpp>
-
-
-namespace std{ namespace tr1{
-
-template <class T> struct tuple_size; // forward declaration
-template < int I, class T> struct tuple_element; // forward declaration
-
-template <class T1, class T2>
-struct tuple_size< ::std::pair<T1, T2> >
- : public ::boost::integral_constant< ::std::size_t, 2>
-{
-};
-
-template <class T1, class T2>
-struct tuple_element<0, ::std::pair<T1, T2> >
-{
- typedef typename std::pair<T1, T2>::first_type type;
-};
-
-template <class T1, class T2>
-struct tuple_element<1, std::pair<T1, T2> >
-{
- typedef typename std::pair<T1, T2>::second_type type;
-};
-
-namespace tuple_detail{
- template <int I, class T1, class T2>
- struct tuple_get_result
- {
- typedef typename boost::mpl::if_c<I==0, T1, T2>::type t1;
- typedef typename boost::add_reference<t1>::type type;
- };
- template <int I, class T1, class T2>
- struct const_tuple_get_result
- {
- typedef typename boost::mpl::if_c<I==0, T1, T2>::type t1;
-# if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x582))
- // I have absolutely no idea why add_const is not working here for Borland!
- // It passes all other free-standing tests, some strange interaction going on
- typedef typename boost::add_reference< const t1 >::type type;
-# else
- typedef typename boost::add_const<t1>::type t2;
- typedef typename boost::add_reference<t2>::type type;
-# endif
- };
-
-template<int I, class T1, class T2>
-inline typename tuple_detail::tuple_get_result<I,T1,T2>::type get(std::pair<T1, T2>& p, const ::boost::true_type&)
-{
- return p.first;
-}
-
-template<int I, class T1, class T2>
-inline typename tuple_detail::const_tuple_get_result<I,T1,T2>::type get(const std::pair<T1, T2>& p, const ::boost::true_type&)
-{
- return p.first;
-}
-
-template<int I, class T1, class T2>
-inline typename tuple_detail::tuple_get_result<I,T1,T2>::type get(std::pair<T1, T2>& p, const ::boost::false_type&)
-{
- return p.second;
-}
-
-template<int I, class T1, class T2>
-inline typename tuple_detail::const_tuple_get_result<I,T1,T2>::type get(const std::pair<T1, T2>& p, const ::boost::false_type&)
-{
- return p.second;
-}
-
-}
-
-template<int I, class T1, class T2>
-inline typename tuple_detail::tuple_get_result<I,T1,T2>::type get(std::pair<T1, T2>& p)
-{
- return tuple_detail::get<I>(p, boost::integral_constant<bool, I==0>());
-}
-
-template<int I, class T1, class T2>
-inline typename tuple_detail::const_tuple_get_result<I,T1,T2>::type get(const std::pair<T1, T2>& p)
-{
- return tuple_detail::get<I>(p, boost::integral_constant<bool, I==0>());
-}
-
-} } // namespaces
-
-#else
-
-#include <boost/tr1/tuple.hpp>
-
-#endif
-
-#endif
-
-#endif
diff --git a/boost/type_index/ctti_type_index.hpp b/boost/type_index/ctti_type_index.hpp
index 611ad92e11..6832adeaf7 100644
--- a/boost/type_index/ctti_type_index.hpp
+++ b/boost/type_index/ctti_type_index.hpp
@@ -22,6 +22,7 @@
#include <boost/type_index/detail/compile_time_type_info.hpp>
#include <cstring>
+#include <boost/functional/hash.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
diff --git a/boost/type_index/detail/compile_time_type_info.hpp b/boost/type_index/detail/compile_time_type_info.hpp
index a2a89ae136..4eb2017ffc 100644
--- a/boost/type_index/detail/compile_time_type_info.hpp
+++ b/boost/type_index/detail/compile_time_type_info.hpp
@@ -11,7 +11,7 @@
/// \file compile_time_type_info.hpp
/// \brief Contains helper macros and implementation details of boost::typeindex::ctti_type_index.
-/// Not intended for inclusion from user's code.
+/// Not intended for inclusion from user's code.
#include <boost/config.hpp>
#include <boost/static_assert.hpp>
@@ -59,9 +59,12 @@
// sizeof("static const char *boost::detail::ctti<") - 1, sizeof("]") - 1, true, "int>::n() [T = int"
// note: checked on 3.1, 3.4
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 1, true, "T = ")
-#elif defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR)
- // sizeof("static contexpr char boost::detail::ctti<T>::s() [with unsigned int I = 0u; T = ") - 1, sizeof("]") - 1
+#elif defined(__GNUC__) && (__GNUC__ < 7) && !defined(BOOST_NO_CXX14_CONSTEXPR)
+ // sizeof("static constexpr char boost::detail::ctti<T>::s() [with unsigned int I = 0u; T = ") - 1, sizeof("]") - 1
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(81, 1, false, "")
+#elif defined(__GNUC__) && (__GNUC__ >= 7) && !defined(BOOST_NO_CXX14_CONSTEXPR)
+ // sizeof("static constexpr char boost::detail::ctti<T>::s() [with unsigned int I = 0; T = ") - 1, sizeof("]") - 1
+ BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(80, 1, false, "")
#elif defined(__GNUC__) && defined(BOOST_NO_CXX14_CONSTEXPR)
// sizeof("static const char* boost::detail::ctti<T>::n() [with T = ") - 1, sizeof("]") - 1
BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(57, 1, false, "")
@@ -72,7 +75,7 @@
#undef BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS
-namespace boost { namespace typeindex { namespace detail {
+namespace boost { namespace typeindex { namespace detail {
template <bool Condition>
BOOST_CXX14_CONSTEXPR inline void assert_compile_time_legths() BOOST_NOEXCEPT {
BOOST_STATIC_ASSERT_MSG(
@@ -149,7 +152,7 @@ namespace boost { namespace typeindex { namespace detail {
BOOST_CXX14_CONSTEXPR inline const char* skip_begining(const char* begin) BOOST_NOEXCEPT {
assert_compile_time_legths<(ArrayLength > ctti_skip_size_at_begin + ctti_skip_size_at_end)>();
return skip_begining_runtime<ArrayLength - ctti_skip_size_at_begin>(
- begin + ctti_skip_size_at_begin,
+ begin + ctti_skip_size_at_begin,
boost::mpl::bool_<ctti_skip_more_at_runtime>()
);
}
@@ -203,7 +206,7 @@ namespace boost { namespace detail {
/// This name must be as short as possible, to avoid code bloat
template <class T>
struct ctti {
-
+
#if !defined(__clang__) && defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR)
//helper functions
template <unsigned int I>
@@ -286,4 +289,3 @@ struct ctti {
}} // namespace boost::detail
#endif // BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP
-
diff --git a/boost/type_index/stl_type_index.hpp b/boost/type_index/stl_type_index.hpp
index be28889962..dcc532d03b 100644
--- a/boost/type_index/stl_type_index.hpp
+++ b/boost/type_index/stl_type_index.hpp
@@ -40,6 +40,12 @@
#include <boost/mpl/if.hpp>
#include <boost/mpl/or.hpp>
+#if !((defined(_MSC_VER) && _MSC_VER > 1600) \
+ || (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ > 5 && defined(__GXX_EXPERIMENTAL_CXX0X__)) \
+ || (defined(__GNUC__) && __GNUC__ > 4 && __cplusplus >= 201103 ))
+# include <boost/functional/hash.hpp>
+#endif
+
#if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
|| (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744)
# include <boost/type_traits/is_signed.hpp>
@@ -174,7 +180,9 @@ inline std::string stl_type_index::pretty_name() const {
inline std::size_t stl_type_index::hash_code() const BOOST_NOEXCEPT {
-#if (defined(_MSC_VER) && _MSC_VER > 1600) || (__GNUC__ == 4 && __GNUC_MINOR__ > 5 && defined(__GXX_EXPERIMENTAL_CXX0X__))
+#if (defined(_MSC_VER) && _MSC_VER > 1600) \
+ || (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ > 5 && defined(__GXX_EXPERIMENTAL_CXX0X__)) \
+ || (defined(__GNUC__) && __GNUC__ > 4 && __cplusplus >= 201103)
return data_->hash_code();
#else
return boost::hash_range(raw_name(), raw_name() + std::strlen(raw_name()));
diff --git a/boost/type_index/type_index_facade.hpp b/boost/type_index/type_index_facade.hpp
index dd35df2caa..110000c33d 100644
--- a/boost/type_index/type_index_facade.hpp
+++ b/boost/type_index/type_index_facade.hpp
@@ -103,7 +103,8 @@ public:
/// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
/// \return Hash code of a type. By default hashes types by raw_name().
- /// \note <boost/functional/hash.hpp> has to be included if this function is used.
+ /// \note Derived class header \b must include <boost/functional/hash.hpp>, \b unless this function is redefined in
+ /// Derived class to not use boost::hash_range().
inline std::size_t hash_code() const BOOST_NOEXCEPT {
const char* const name_raw = derived().raw_name();
return boost::hash_range(name_raw, name_raw + std::strlen(name_raw));
diff --git a/boost/type_traits.hpp b/boost/type_traits.hpp
index 93a992d38c..dbc8c952c9 100644
--- a/boost/type_traits.hpp
+++ b/boost/type_traits.hpp
@@ -136,6 +136,7 @@
#include <boost/type_traits/remove_bounds.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_cv_ref.hpp>
#include <boost/type_traits/remove_extent.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/type_traits/remove_reference.hpp>
diff --git a/boost/type_traits/add_const.hpp b/boost/type_traits/add_const.hpp
index a9fb781c78..2d60118276 100644
--- a/boost/type_traits/add_const.hpp
+++ b/boost/type_traits/add_const.hpp
@@ -41,6 +41,12 @@ namespace boost {
typedef T& type;
};
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <class T> using add_const_t = typename add_const<T>::type;
+
+#endif
+
} // namespace boost
#endif // BOOST_TT_ADD_CONST_HPP_INCLUDED
diff --git a/boost/type_traits/add_cv.hpp b/boost/type_traits/add_cv.hpp
index e62ddee0c4..425d019bf6 100644
--- a/boost/type_traits/add_cv.hpp
+++ b/boost/type_traits/add_cv.hpp
@@ -36,6 +36,12 @@ template <class T> struct add_cv{ typedef T const volatile type; };
template <class T> struct add_cv<T&>{ typedef T& type; };
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <class T> using add_cv_t = typename add_cv<T>::type;
+
+#endif
+
} // namespace boost
#endif // BOOST_TT_ADD_CV_HPP_INCLUDED
diff --git a/boost/type_traits/add_lvalue_reference.hpp b/boost/type_traits/add_lvalue_reference.hpp
index 41851a1f34..26b74e67ca 100644
--- a/boost/type_traits/add_lvalue_reference.hpp
+++ b/boost/type_traits/add_lvalue_reference.hpp
@@ -22,6 +22,12 @@ template <class T> struct add_lvalue_reference<T&&>
};
#endif
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <class T> using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;
+
+#endif
+
}
#endif // BOOST_TYPE_TRAITS_EXT_ADD_LVALUE_REFERENCE__HPP
diff --git a/boost/type_traits/add_pointer.hpp b/boost/type_traits/add_pointer.hpp
index 745f63a084..85ad33a8d9 100644
--- a/boost/type_traits/add_pointer.hpp
+++ b/boost/type_traits/add_pointer.hpp
@@ -56,6 +56,12 @@ struct add_pointer
#endif
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <class T> using add_pointer_t = typename add_pointer<T>::type;
+
+#endif
+
} // namespace boost
#endif // BOOST_TT_ADD_POINTER_HPP_INCLUDED
diff --git a/boost/type_traits/add_reference.hpp b/boost/type_traits/add_reference.hpp
index 3c914154ee..33e9bc79be 100644
--- a/boost/type_traits/add_reference.hpp
+++ b/boost/type_traits/add_reference.hpp
@@ -54,6 +54,13 @@ template <> struct add_reference<const volatile void> { typedef const volatile v
template <> struct add_reference<volatile void> { typedef volatile void type; };
#endif
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template <class T> using add_reference_t = typename add_reference<T>::type;
+
+#endif
+
+
} // namespace boost
#endif // BOOST_TT_ADD_REFERENCE_HPP_INCLUDED
diff --git a/boost/type_traits/add_rvalue_reference.hpp b/boost/type_traits/add_rvalue_reference.hpp
index 44ead34803..ad64894f77 100644
--- a/boost/type_traits/add_rvalue_reference.hpp
+++ b/boost/type_traits/add_rvalue_reference.hpp
@@ -58,6 +58,12 @@ template <class T> struct add_rvalue_reference
typedef typename boost::type_traits_detail::add_rvalue_reference_imp<T>::type type;
};
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <class T> using add_rvalue_reference_t = typename add_rvalue_reference<T>::type;
+
+#endif
+
} // namespace boost
#endif // BOOST_TYPE_TRAITS_EXT_ADD_RVALUE_REFERENCE__HPP
diff --git a/boost/type_traits/add_volatile.hpp b/boost/type_traits/add_volatile.hpp
index 24f515c802..253751a578 100644
--- a/boost/type_traits/add_volatile.hpp
+++ b/boost/type_traits/add_volatile.hpp
@@ -35,6 +35,12 @@ template <class T> struct add_volatile{ typedef T volatile type; };
template <class T> struct add_volatile<T&>{ typedef T& type; };
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <class T> using add_volatile_t = typename add_volatile<T>::type;
+
+#endif
+
} // namespace boost
#endif // BOOST_TT_ADD_VOLATILE_HPP_INCLUDED
diff --git a/boost/type_traits/conditional.hpp b/boost/type_traits/conditional.hpp
index b7e82dbe82..5890198ba2 100644
--- a/boost/type_traits/conditional.hpp
+++ b/boost/type_traits/conditional.hpp
@@ -14,6 +14,12 @@ namespace boost {
template <bool b, class T, class U> struct conditional { typedef T type; };
template <class T, class U> struct conditional<false, T, U> { typedef U type; };
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <bool b, class T, class U> using conditional_t = typename conditional<b, T, U>::type;
+
+#endif
+
} // namespace boost
diff --git a/boost/type_traits/copy_cv.hpp b/boost/type_traits/copy_cv.hpp
index 1605ca3356..2f3dc37adc 100644
--- a/boost/type_traits/copy_cv.hpp
+++ b/boost/type_traits/copy_cv.hpp
@@ -29,6 +29,12 @@ public:
typedef typename boost::conditional<boost::is_volatile<U>::value, typename boost::add_volatile<CT>::type, CT>::type type;
};
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <class T, class U> using copy_cv_t = typename copy_cv<T, U>::type;
+
+#endif
+
} // namespace boost
#endif // #ifndef BOOST_TYPE_TRAITS_COPY_CV_HPP_INCLUDED
diff --git a/boost/type_traits/decay.hpp b/boost/type_traits/decay.hpp
index 4e8118433e..5b28d052fc 100644
--- a/boost/type_traits/decay.hpp
+++ b/boost/type_traits/decay.hpp
@@ -37,6 +37,12 @@ namespace boost
typedef typename boost::detail::decay_imp<Ty, boost::is_array<Ty>::value, boost::is_function<Ty>::value>::type type;
};
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <class T> using decay_t = typename decay<T>::type;
+
+#endif
+
} // namespace boost
diff --git a/boost/type_traits/floating_point_promotion.hpp b/boost/type_traits/floating_point_promotion.hpp
index 993e14ef4b..0e709b74ae 100644
--- a/boost/type_traits/floating_point_promotion.hpp
+++ b/boost/type_traits/floating_point_promotion.hpp
@@ -14,6 +14,12 @@ namespace boost {
template<> struct floating_point_promotion<float volatile>{ typedef double volatile type; };
template<> struct floating_point_promotion<float const volatile> { typedef double const volatile type; };
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <class T> using floating_point_promotion_t = typename floating_point_promotion<T>::type;
+
+#endif
+
}
#endif // #ifndef FILE_boost_type_traits_floating_point_promotion_hpp_INCLUDED
diff --git a/boost/type_traits/integral_promotion.hpp b/boost/type_traits/integral_promotion.hpp
index 0478f56349..526f90ca99 100644
--- a/boost/type_traits/integral_promotion.hpp
+++ b/boost/type_traits/integral_promotion.hpp
@@ -175,6 +175,12 @@ public:
typedef typename boost::type_traits::detail::integral_promotion<T, tag_type::value>::type type;
};
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <class T> using integral_promotion_t = typename integral_promotion<T>::type;
+
+#endif
+
}
#endif // #ifndef FILE_boost_type_traits_integral_promotion_hpp_INCLUDED
diff --git a/boost/type_traits/make_signed.hpp b/boost/type_traits/make_signed.hpp
index 0d2d5df61a..6d8b1fb8d4 100644
--- a/boost/type_traits/make_signed.hpp
+++ b/boost/type_traits/make_signed.hpp
@@ -125,6 +125,12 @@ public:
>::type type;
};
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <class T> using make_signed_t = typename make_signed<T>::type;
+
+#endif
+
} // namespace boost
#endif // BOOST_TT_ADD_REFERENCE_HPP_INCLUDED
diff --git a/boost/type_traits/make_unsigned.hpp b/boost/type_traits/make_unsigned.hpp
index 4b21ebaeb2..17a8a5b929 100644
--- a/boost/type_traits/make_unsigned.hpp
+++ b/boost/type_traits/make_unsigned.hpp
@@ -124,6 +124,12 @@ public:
>::type type;
};
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <class T> using make_unsigned_t = typename make_unsigned<T>::type;
+
+#endif
+
} // namespace boost
#endif // BOOST_TT_ADD_REFERENCE_HPP_INCLUDED
diff --git a/boost/type_traits/promote.hpp b/boost/type_traits/promote.hpp
index 587617a287..1678e1ca3e 100644
--- a/boost/type_traits/promote.hpp
+++ b/boost/type_traits/promote.hpp
@@ -14,6 +14,12 @@ namespace boost {
template<class T> struct promote : public integral_promotion<typename floating_point_promotion<T>::type>{};
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <class T> using promote_t = typename promote<T>::type;
+
+#endif
+
}
#endif // #ifndef FILE_boost_type_traits_promote_hpp_INCLUDED
diff --git a/boost/type_traits/remove_all_extents.hpp b/boost/type_traits/remove_all_extents.hpp
index 90c90d3523..b9736db57e 100644
--- a/boost/type_traits/remove_all_extents.hpp
+++ b/boost/type_traits/remove_all_extents.hpp
@@ -30,6 +30,12 @@ template <class T> struct remove_all_extents<T const volatile[]> : public remove
#endif
#endif
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <class T> using remove_all_extents_t = typename remove_all_extents<T>::type;
+
+#endif
+
} // namespace boost
#endif // BOOST_TT_REMOVE_BOUNDS_HPP_INCLUDED
diff --git a/boost/type_traits/remove_bounds.hpp b/boost/type_traits/remove_bounds.hpp
index 56988d24e0..cd0565d28f 100644
--- a/boost/type_traits/remove_bounds.hpp
+++ b/boost/type_traits/remove_bounds.hpp
@@ -16,6 +16,13 @@ namespace boost
template <class T> struct remove_bounds : public remove_extent<T> {};
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template <class T> using remove_bounds_t = typename remove_bounds<T>::type;
+
+#endif
+
+
} // namespace boost
#endif // BOOST_TT_REMOVE_BOUNDS_HPP_INCLUDED
diff --git a/boost/type_traits/remove_const.hpp b/boost/type_traits/remove_const.hpp
index e238962c6d..6f1a193740 100644
--- a/boost/type_traits/remove_const.hpp
+++ b/boost/type_traits/remove_const.hpp
@@ -28,6 +28,12 @@ namespace boost {
#endif
#endif
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <class T> using remove_const_t = typename remove_const<T>::type;
+
+#endif
+
} // namespace boost
#endif // BOOST_TT_REMOVE_CONST_HPP_INCLUDED
diff --git a/boost/type_traits/remove_cv.hpp b/boost/type_traits/remove_cv.hpp
index 08393cfb81..57a96f29d6 100644
--- a/boost/type_traits/remove_cv.hpp
+++ b/boost/type_traits/remove_cv.hpp
@@ -34,6 +34,11 @@ template <class T> struct remove_cv<T volatile[]>{ typedef T type[]; };
#endif
#endif
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <class T> using remove_cv_t = typename remove_cv<T>::type;
+
+#endif
} // namespace boost
diff --git a/boost/type_traits/remove_cv_ref.hpp b/boost/type_traits/remove_cv_ref.hpp
new file mode 100644
index 0000000000..118945a6a0
--- /dev/null
+++ b/boost/type_traits/remove_cv_ref.hpp
@@ -0,0 +1,30 @@
+
+// (C) Copyright Peter Dimov 2017.
+// 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.
+
+
+#ifndef BOOST_TT_REMOVE_CV_REF_HPP_INCLUDED
+#define BOOST_TT_REMOVE_CV_REF_HPP_INCLUDED
+
+#include <boost/config.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+
+namespace boost {
+
+ template <class T> struct remove_cv_ref: remove_cv<typename remove_reference<T>::type> {};
+
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <class T> using remove_cv_ref_t = typename remove_cv_ref<T>::type;
+
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_REMOVE_CV_REF_HPP_INCLUDED
diff --git a/boost/type_traits/remove_extent.hpp b/boost/type_traits/remove_extent.hpp
index b6528e525b..55d57301b7 100644
--- a/boost/type_traits/remove_extent.hpp
+++ b/boost/type_traits/remove_extent.hpp
@@ -30,6 +30,12 @@ template <typename T> struct remove_extent<T const volatile[]> { typedef T const
#endif
#endif
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <class T> using remove_extent_t = typename remove_extent<T>::type;
+
+#endif
+
} // namespace boost
#endif // BOOST_TT_REMOVE_BOUNDS_HPP_INCLUDED
diff --git a/boost/type_traits/remove_pointer.hpp b/boost/type_traits/remove_pointer.hpp
index 921665266f..a7baa765f0 100644
--- a/boost/type_traits/remove_pointer.hpp
+++ b/boost/type_traits/remove_pointer.hpp
@@ -72,6 +72,12 @@ template <class T> struct remove_pointer<T*const volatile>{ typedef T type; };
#endif
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <class T> using remove_pointer_t = typename remove_pointer<T>::type;
+
+#endif
+
} // namespace boost
#endif // BOOST_TT_REMOVE_POINTER_HPP_INCLUDED
diff --git a/boost/type_traits/remove_reference.hpp b/boost/type_traits/remove_reference.hpp
index f75e67783b..70949fbb2a 100644
--- a/boost/type_traits/remove_reference.hpp
+++ b/boost/type_traits/remove_reference.hpp
@@ -48,6 +48,11 @@ template <class T> struct remove_reference<T&volatile>{ typedef T type; };
template <class T> struct remove_reference<T&const volatile>{ typedef T type; };
#endif
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <class T> using remove_reference_t = typename remove_reference<T>::type;
+
+#endif
} // namespace boost
diff --git a/boost/type_traits/remove_volatile.hpp b/boost/type_traits/remove_volatile.hpp
index f5870f317f..bf2c55796a 100644
--- a/boost/type_traits/remove_volatile.hpp
+++ b/boost/type_traits/remove_volatile.hpp
@@ -28,6 +28,11 @@ namespace boost {
#endif
#endif
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+ template <class T> using remove_volatile_t = typename remove_volatile<T>::type;
+
+#endif
} // namespace boost
diff --git a/boost/type_traits/type_identity.hpp b/boost/type_traits/type_identity.hpp
index 6d2dd5b4dc..73cb3f3f9e 100644
--- a/boost/type_traits/type_identity.hpp
+++ b/boost/type_traits/type_identity.hpp
@@ -17,6 +17,13 @@ template<class T> struct type_identity
typedef T type;
};
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template <class T> using type_identity_t = typename type_identity<T>::type;
+
+#endif
+
+
} // namespace boost
#endif // #ifndef BOOST_TYPE_TRAITS_TYPE_IDENTITY_HPP_INCLUDED
diff --git a/boost/typeof/decltype.hpp b/boost/typeof/decltype.hpp
new file mode 100644
index 0000000000..7e990a8cef
--- /dev/null
+++ b/boost/typeof/decltype.hpp
@@ -0,0 +1,34 @@
+// Copyright (C) 2006 Arkadiy Vertleyb
+// Copyright (C) 2017 Daniela Engert
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TYPEOF_DECLTYPE_HPP_INCLUDED
+# define BOOST_TYPEOF_DECLTYPE_HPP_INCLUDED
+
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+
+namespace boost { namespace type_of {
+ template<typename T>
+ using remove_cv_ref_t = typename remove_cv<typename remove_reference<T>::type>::type;
+}}
+
+#define BOOST_TYPEOF(expr) boost::type_of::remove_cv_ref_t<decltype(expr)>
+#define BOOST_TYPEOF_TPL BOOST_TYPEOF
+
+#define BOOST_TYPEOF_NESTED_TYPEDEF_TPL(name,expr) \
+ struct name {\
+ typedef BOOST_TYPEOF_TPL(expr) type;\
+ };
+
+#define BOOST_TYPEOF_NESTED_TYPEDEF(name,expr) \
+ struct name {\
+ typedef BOOST_TYPEOF(expr) type;\
+ };
+
+#define BOOST_TYPEOF_REGISTER_TYPE(x)
+#define BOOST_TYPEOF_REGISTER_TEMPLATE(x, params)
+
+#endif //BOOST_TYPEOF_DECLTYPE_HPP_INCLUDED
+
diff --git a/boost/typeof/msvc/typeof_impl.hpp b/boost/typeof/msvc/typeof_impl.hpp
index 74ebc70738..3071efb749 100644
--- a/boost/typeof/msvc/typeof_impl.hpp
+++ b/boost/typeof/msvc/typeof_impl.hpp
@@ -15,9 +15,7 @@
# include <boost/type_traits/is_function.hpp>
# include <boost/utility/enable_if.hpp>
-# if BOOST_WORKAROUND(BOOST_MSVC,>=1310)
-# include <typeinfo>
-# endif
+# include <typeinfo>
namespace boost
{
@@ -25,7 +23,7 @@ namespace boost
{
//Compile time constant code
-# if BOOST_WORKAROUND(BOOST_MSVC,>=1300) && defined(_MSC_EXTENSIONS)
+# if defined(_MSC_EXTENSIONS)
template<int N> struct the_counter;
template<typename T,int N = 5/*for similarity*/>
@@ -85,26 +83,7 @@ namespace boost
//Typeof code
-# if BOOST_WORKAROUND(BOOST_MSVC,==1300)
- template<typename ID>
- struct msvc_extract_type
- {
- template<bool>
- struct id2type_impl;
-
- typedef id2type_impl<true> id2type;
- };
-
- template<typename T, typename ID>
- struct msvc_register_type : msvc_extract_type<ID>
- {
- template<>
- struct id2type_impl<true> //VC7.0 specific bugfeature
- {
- typedef T type;
- };
- };
-#elif BOOST_WORKAROUND(BOOST_MSVC,>=1400)
+# if BOOST_WORKAROUND(BOOST_MSVC,>=1400)
struct msvc_extract_type_default_param {};
template<typename ID, typename T = msvc_extract_type_default_param>
@@ -153,60 +132,7 @@ namespace boost
};
};
# endif
-// EAN: preprocess this block out on advice of Peder Holt
-// to eliminate errors in type_traits/common_type.hpp
-# if 0 //BOOST_WORKAROUND(BOOST_MSVC,==1310)
- template<const std::type_info& ref_type_info>
- struct msvc_typeid_wrapper {
- typedef typename msvc_extract_type<msvc_typeid_wrapper>::id2type id2type;
- typedef typename id2type::type wrapped_type;
- typedef typename wrapped_type::type type;
- };
- //This class is used for registering the type T. encode_type<T> is mapped against typeid(encode_type<T>).
- //msvc_typeid_wrapper<typeid(encode_type<T>)> will now have a type typedef that equals encode_type<T>.
- template<typename T>
- struct encode_type
- {
- typedef encode_type<T> input_type;
- //Invoke registration of encode_type<T>. typeid(encode_type<T>) is now mapped to encode_type<T>. Do not use registered_type for anything.
- //The reason for registering encode_type<T> rather than T, is that VC handles typeid(function reference) poorly. By adding another
- //level of indirection, we solve this problem.
- typedef typename msvc_register_type<input_type,msvc_typeid_wrapper<typeid(input_type)> >::id2type registered_type;
- typedef T type;
- };
-
- template<typename T> typename disable_if<
- typename is_function<T>::type,
- typename encode_type<T>::input_type>::type encode_start(T const&);
-
- template<typename T> typename enable_if<
- typename is_function<T>::type,
- typename encode_type<T>::input_type>::type encode_start(T&);
-
- template<typename Organizer, typename T>
- msvc_register_type<T,Organizer> typeof_register_type(const T&);
-
-
-# define BOOST_TYPEOF(expr) \
- boost::type_of::msvc_typeid_wrapper<typeid(boost::type_of::encode_start(expr))>::type
-
-# define BOOST_TYPEOF_TPL(expr) typename BOOST_TYPEOF(expr)
-# define BOOST_TYPEOF_NESTED_TYPEDEF_TPL(name,expr) \
-struct name {\
- enum {_typeof_register_value=sizeof(typeid(boost::type_of::typeof_register_type<name>(expr)))};\
- typedef typename boost::type_of::msvc_extract_type<name>::id2type id2type;\
- typedef typename id2type::type type;\
-};
-
-# define BOOST_TYPEOF_NESTED_TYPEDEF(name,expr) \
-struct name {\
- enum {_typeof_register_value=sizeof(typeid(boost::type_of::typeof_register_type<name>(expr)))};\
- typedef boost::type_of::msvc_extract_type<name>::id2type id2type;\
- typedef id2type::type type;\
-};
-
-# else
template<int ID>
struct msvc_typeid_wrapper {
typedef typename msvc_extract_type<mpl::int_<ID> >::id2type id2type;
@@ -242,7 +168,6 @@ struct name {\
{
typedef char(*type)[encode_type<T>::value];
};
-# if BOOST_WORKAROUND(BOOST_MSVC,>=1310)
template<typename T> typename disable_if<
typename is_function<T>::type,
typename sizer<T>::type>::type encode_start(T const&);
@@ -250,10 +175,6 @@ struct name {\
template<typename T> typename enable_if<
typename is_function<T>::type,
typename sizer<T>::type>::type encode_start(T&);
-# else
- template<typename T>
- typename sizer<T>::type encode_start(T const&);
-# endif
template<typename Organizer, typename T>
msvc_register_type<T,Organizer> typeof_register_type(const T&,Organizer* =0);
@@ -264,19 +185,18 @@ struct name {\
# define BOOST_TYPEOF_NESTED_TYPEDEF_TPL(name,expr) \
struct name {\
- BOOST_STATIC_CONSTANT(int,_typeof_register_value=sizeof(boost::type_of::typeof_register_type<name>(expr)));\
+ enum {_typeof_register_value=sizeof(boost::type_of::typeof_register_type<name>(expr))};\
typedef typename boost::type_of::msvc_extract_type<name>::id2type id2type;\
typedef typename id2type::type type;\
};
# define BOOST_TYPEOF_NESTED_TYPEDEF(name,expr) \
struct name {\
- BOOST_STATIC_CONSTANT(int,_typeof_register_value=sizeof(boost::type_of::typeof_register_type<name>(expr)));\
+ enum {_typeof_register_value=sizeof(boost::type_of::typeof_register_type<name>(expr))};\
typedef boost::type_of::msvc_extract_type<name>::id2type id2type;\
typedef id2type::type type;\
};
-#endif
}
}
diff --git a/boost/typeof/native.hpp b/boost/typeof/native.hpp
index 8197e28669..8197e28669 100755..100644
--- a/boost/typeof/native.hpp
+++ b/boost/typeof/native.hpp
diff --git a/boost/typeof/register_fundamental.hpp b/boost/typeof/register_fundamental.hpp
index 3a15888d08..a6164bafa3 100755..100644
--- a/boost/typeof/register_fundamental.hpp
+++ b/boost/typeof/register_fundamental.hpp
@@ -34,8 +34,7 @@ BOOST_TYPEOF_REGISTER_TYPE(long double)
BOOST_TYPEOF_REGISTER_TYPE(wchar_t)
#endif
-#if (defined(BOOST_MSVC) && (BOOST_MSVC == 1200)) \
- || (defined(BOOST_INTEL_CXX_VERSION) && defined(_MSC_VER) && (BOOST_INTEL_CXX_VERSION <= 600)) \
+#if (defined(BOOST_INTEL_CXX_VERSION) && defined(_MSC_VER) && (BOOST_INTEL_CXX_VERSION <= 600)) \
|| (defined(__BORLANDC__) && (__BORLANDC__ == 0x600) && (_MSC_VER == 1200))
BOOST_TYPEOF_REGISTER_TYPE(unsigned __int8)
BOOST_TYPEOF_REGISTER_TYPE(__int8)
diff --git a/boost/typeof/typeof.hpp b/boost/typeof/typeof.hpp
index 4d56964980..1efa3dc8c4 100644
--- a/boost/typeof/typeof.hpp
+++ b/boost/typeof/typeof.hpp
@@ -13,7 +13,15 @@
# error both typeof emulation and native mode requested
#endif
-#if defined(__COMO__)
+#include <boost/config.hpp>
+
+#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !defined(BOOST_TYPEOF_EMULATION)
+# define BOOST_TYPEOF_DECLTYPE
+# ifndef BOOST_TYPEOF_NATIVE
+# define BOOST_TYPEOF_NATIVE
+# endif
+
+#elif defined(__COMO__)
# ifdef __GNUG__
# ifndef BOOST_TYPEOF_EMULATION
# ifndef BOOST_TYPEOF_NATIVE
@@ -49,7 +57,7 @@
# endif
# endif
-#elif defined(__GNUC__)
+#elif defined(__GNUC__) || defined(__clang__)
# ifndef BOOST_TYPEOF_EMULATION
# ifndef BOOST_TYPEOF_NATIVE
# define BOOST_TYPEOF_NATIVE
@@ -100,17 +108,7 @@
# define MSVC_TYPEOF_HACK
# endif
#elif defined(_MSC_VER)
-# if (_MSC_VER <= 1300) // 6.5, 7.0
-# ifndef BOOST_TYPEOF_EMULATION
-# ifndef BOOST_TYPEOF_NATIVE
-# define BOOST_TYPEOF_NATIVE
-# endif
-# include <boost/typeof/msvc/typeof_impl.hpp>
-# define MSVC_TYPEOF_HACK
-# else
-# error typeof emulation is not supported
-# endif
-# elif (_MSC_VER >= 1310) // 7.1 ->
+# if (_MSC_VER >= 1310) // 7.1 ->
# ifndef BOOST_TYPEOF_EMULATION
# ifndef BOOST_TYPEOF_NATIVE
# ifndef _MSC_EXTENSIONS
@@ -171,6 +169,13 @@
# define BOOST_TYPEOF_KEYWORD __typeof__
# endif
# endif
+#elif defined(__IBM__TYPEOF__)
+# ifndef BOOST_TYPEOF_EMULATION
+# ifndef BOOST_TYPEOF_NATIVE
+# define BOOST_TYPEOF_NATIVE
+# endif
+# define BOOST_TYPEOF_KEYWORD __typeof__
+# endif
#else //unknown compiler
# ifndef BOOST_TYPEOF_NATIVE
# ifndef BOOST_TYPEOF_EMULATION
@@ -206,7 +211,11 @@
#elif defined(BOOST_TYPEOF_NATIVE)
# define BOOST_TYPEOF_TEXT "using native typeof"
# include <boost/typeof/message.hpp>
-# include <boost/typeof/native.hpp>
+# ifdef BOOST_TYPEOF_DECLTYPE
+# include <boost/typeof/decltype.hpp>
+# else
+# include <boost/typeof/native.hpp>
+# endif
#else
# error typeof configuration error
#endif
diff --git a/boost/unordered/detail/fwd.hpp b/boost/unordered/detail/fwd.hpp
index 6a84204200..2e0c63073e 100644
--- a/boost/unordered/detail/fwd.hpp
+++ b/boost/unordered/detail/fwd.hpp
@@ -20,7 +20,7 @@
#endif
#elif defined(_LIBCPP_VERSION)
// https://github.com/llvm-mirror/libcxx/blob/release_30/include/utility#L206
-#if LIBCPP_VERSION >= 3000
+#if _LIBCPP_VERSION >= 3000
#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
#endif
#elif defined(BOOST_MSVC)
@@ -32,6 +32,8 @@
#endif
#endif
+// TODO: Use piecewise construction by default? Is it safe to assume that an
+// unknown library has it?
#if !defined(BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT)
#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 0
#endif
diff --git a/boost/unordered/detail/implementation.hpp b/boost/unordered/detail/implementation.hpp
index c293ae2f50..5750a4c67f 100644
--- a/boost/unordered/detail/implementation.hpp
+++ b/boost/unordered/detail/implementation.hpp
@@ -1,4 +1,3 @@
-
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-2016 Daniel James
//
@@ -19,6 +18,8 @@
#include <boost/iterator/iterator_categories.hpp>
#include <boost/limits.hpp>
#include <boost/move/move.hpp>
+#include <boost/predef.h>
+#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
@@ -47,10 +48,6 @@
#include <stdexcept>
#include <utility>
-#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
-#include <tuple>
-#endif
-
#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
#include <type_traits>
#endif
@@ -61,24 +58,25 @@
// Unless documented elsewhere these configuration macros should be considered
// an implementation detail, I'll try not to break them, but you never know.
-// BOOST_UNORDERED_EMPLACE_LIMIT = The maximum number of parameters in emplace
-// (not including things like hints). Don't set it to a lower value, as that
-// might break something.
+// Use Sun C++ workarounds
+// I'm not sure which versions of the compiler require these workarounds, so
+// I'm just using them of everything older than the current test compilers
+// (as of May 2017).
-#if !defined BOOST_UNORDERED_EMPLACE_LIMIT
-#define BOOST_UNORDERED_EMPLACE_LIMIT 11
+#if !defined(BOOST_UNORDERED_SUN_WORKAROUNDS1)
+#if BOOST_COMP_SUNPRO && BOOST_COMP_SUNPRO < BOOST_VERSION_NUMBER(5, 20, 0)
+#define BOOST_UNORDERED_SUN_WORKAROUNDS1 1
+#else
+#define BOOST_UNORDERED_SUN_WORKAROUNDS1 0
+#endif
#endif
-// BOOST_UNORDERED_INTEROPERABLE_NODES - Use the same node type for
-// containers with unique and equivalent keys.
-//
-// 0 = Use different nodes
-// 1 = Use ungrouped nodes everywhere
-//
-// Might add an extra value to use grouped nodes everywhere later.
+// BOOST_UNORDERED_EMPLACE_LIMIT = The maximum number of parameters in
+// emplace (not including things like hints). Don't set it to a lower value, as
+// that might break something.
-#if !defined(BOOST_UNORDERED_INTEROPERABLE_NODES)
-#define BOOST_UNORDERED_INTEROPERABLE_NODES 0
+#if !defined BOOST_UNORDERED_EMPLACE_LIMIT
+#define BOOST_UNORDERED_EMPLACE_LIMIT 10
#endif
// BOOST_UNORDERED_USE_ALLOCATOR_TRAITS - Pick which version of
@@ -104,13 +102,106 @@
#define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0
#endif
+// BOOST_UNORDERED_TUPLE_ARGS
+//
+// Maximum number of std::tuple members to support, or 0 if std::tuple
+// isn't avaiable. More are supported when full C++11 is used.
+
+// Already defined, so do nothing
+#if defined(BOOST_UNORDERED_TUPLE_ARGS)
+
+// Assume if we have C++11 tuple it's properly variadic,
+// and just use a max number of 10 arguments.
+#elif !defined(BOOST_NO_CXX11_HDR_TUPLE)
+#define BOOST_UNORDERED_TUPLE_ARGS 10
+
+// Visual C++ has a decent enough tuple for piecewise construction,
+// so use that if available, using _VARIADIC_MAX for the maximum
+// number of parameters. Note that this comes after the check
+// for a full C++11 tuple.
+#elif defined(BOOST_MSVC)
+#if !BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
+#define BOOST_UNORDERED_TUPLE_ARGS 0
+#elif defined(_VARIADIC_MAX)
+#define BOOST_UNORDERED_TUPLE_ARGS _VARIADIC_MAX
+#else
+#define BOOST_UNORDERED_TUPLE_ARGS 5
+#endif
+
+// Assume that we don't have std::tuple
+#else
+#define BOOST_UNORDERED_TUPLE_ARGS 0
+#endif
+
+#if BOOST_UNORDERED_TUPLE_ARGS
+#include <tuple>
+#endif
+
+// BOOST_UNORDERED_CXX11_CONSTRUCTION
+//
+// Use C++11 construction, requires variadic arguments, good construct support
+// in allocator_traits and piecewise construction of std::pair
+// Otherwise allocators aren't used for construction/destruction
+
+#if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT && \
+ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && BOOST_UNORDERED_TUPLE_ARGS
+#if BOOST_COMP_SUNPRO && BOOST_LIB_STD_GNU
+// Sun C++ std::pair piecewise construction doesn't seem to be exception safe.
+// (At least for Sun C++ 12.5 using libstdc++).
+#define BOOST_UNORDERED_CXX11_CONSTRUCTION 0
+#elif BOOST_COMP_GNUC && BOOST_COMP_GNUC < BOOST_VERSION_NUMBER(4, 7, 0)
+// Piecewise construction in GCC 4.6 doesn't work for uncopyable types.
+#define BOOST_UNORDERED_CXX11_CONSTRUCTION 0
+#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 0 && \
+ !defined(BOOST_NO_SFINAE_EXPR)
+#define BOOST_UNORDERED_CXX11_CONSTRUCTION 1
+#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
+#define BOOST_UNORDERED_CXX11_CONSTRUCTION 1
+#endif
+#endif
+
+#if !defined(BOOST_UNORDERED_CXX11_CONSTRUCTION)
+#define BOOST_UNORDERED_CXX11_CONSTRUCTION 0
+#endif
+
+// BOOST_UNORDERED_SUPPRESS_DEPRECATED
+//
+// Define to stop deprecation attributes
+
+#if defined(BOOST_UNORDERED_SUPPRESS_DEPRECATED)
+#define BOOST_UNORDERED_DEPRECATED(msg)
+#endif
+
+// BOOST_UNORDERED_DEPRECATED
+//
+// Wrapper around various depreaction attributes.
+
+#if defined(__has_cpp_attribute) && \
+ (!defined(__cplusplus) || __cplusplus >= 201402)
+#if __has_cpp_attribute(deprecated) && !defined(BOOST_UNORDERED_DEPRECATED)
+#define BOOST_UNORDERED_DEPRECATED(msg) [[deprecated(msg)]]
+#endif
+#endif
+
+#if !defined(BOOST_UNORDERED_DEPRECATED)
+#if defined(__GNUC__) && __GNUC__ >= 4
+#define BOOST_UNORDERED_DEPRECATED(msg) __attribute__((deprecated))
+#elif defined(_MSC_VER) && _MSC_VER >= 1400
+#define BOOST_UNORDERED_DEPRECATED(msg) __declspec(deprecated(msg))
+#elif defined(_MSC_VER) && _MSC_VER >= 1310
+#define BOOST_UNORDERED_DEPRECATED(msg) __declspec(deprecated)
+#else
+#define BOOST_UNORDERED_DEPRECATED(msg)
+#endif
+#endif
+
namespace boost {
namespace unordered {
namespace iterator_detail {
template <typename Node> struct iterator;
template <typename Node> struct c_iterator;
-template <typename Node, typename Policy> struct l_iterator;
-template <typename Node, typename Policy> struct cl_iterator;
+template <typename Node> struct l_iterator;
+template <typename Node> struct cl_iterator;
}
}
}
@@ -122,28 +213,27 @@ namespace detail {
template <typename Types> struct table;
template <typename NodePointer> struct bucket;
struct ptr_bucket;
-template <typename Types> struct table_impl;
-template <typename Types> struct grouped_table_impl;
-template <typename A, typename T> struct unique_node;
+template <typename A, typename T> struct node;
template <typename T> struct ptr_node;
-template <typename Types> struct table_impl;
-
-template <typename A, typename T> struct grouped_node;
-template <typename T> struct grouped_ptr_node;
-template <typename Types> struct grouped_table_impl;
-template <typename N> struct node_algo;
-template <typename N> struct grouped_node_algo;
static const float minimum_max_load_factor = 1e-3f;
static const std::size_t default_bucket_count = 11;
+
struct move_tag
{
};
+
struct empty_emplace
{
};
+struct no_key
+{
+ no_key() {}
+ template <class T> no_key(T const&) {}
+};
+
namespace func {
template <class T> inline void ignore_unused_variable_warning(T const&) {}
}
@@ -190,7 +280,7 @@ template <class T> struct prime_list_template
{
static std::size_t const value[];
-#if !defined(SUNPRO_CC)
+#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
static std::ptrdiff_t const length;
#else
static std::ptrdiff_t const length =
@@ -202,7 +292,7 @@ template <class T>
std::size_t const prime_list_template<T>::value[] = {
BOOST_PP_SEQ_ENUM(BOOST_UNORDERED_PRIMES)};
-#if !defined(SUNPRO_CC)
+#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
template <class T>
std::ptrdiff_t const prime_list_template<T>::length = BOOST_PP_SEQ_SIZE(
BOOST_UNORDERED_PRIMES);
@@ -439,16 +529,17 @@ struct convert_from_anything
template <typename T> convert_from_anything(T const&);
};
-namespace func {
-// This is a bit nasty, when constructing the individual members
-// of a std::pair, need to cast away 'const'. For modern compilers,
-// should be able to use std::piecewise_construct instead.
-template <typename T> T* const_cast_pointer(T* x) { return x; }
-template <typename T> T* const_cast_pointer(T const* x)
+// Get a pointer from a smart pointer, a bit simpler than pointer_traits
+// as we already know the pointer type that we want.
+template <typename T> struct pointer
{
- return const_cast<T*>(x);
-}
-}
+ template <typename Ptr> static T* get(Ptr const& x)
+ {
+ return static_cast<T*>(x.operator->());
+ }
+
+ template <typename T2> static T* get(T2* x) { return static_cast<T*>(x); }
+};
////////////////////////////////////////////////////////////////////////////
// emplace_args
@@ -458,20 +549,12 @@ template <typename T> T* const_cast_pointer(T const* x)
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
-#define BOOST_UNORDERED_EMPLACE_ARGS1(a0) a0
-#define BOOST_UNORDERED_EMPLACE_ARGS2(a0, a1) a0, a1
-#define BOOST_UNORDERED_EMPLACE_ARGS3(a0, a1, a2) a0, a1, a2
-
#define BOOST_UNORDERED_EMPLACE_TEMPLATE typename... Args
#define BOOST_UNORDERED_EMPLACE_ARGS BOOST_FWD_REF(Args)... args
#define BOOST_UNORDERED_EMPLACE_FORWARD boost::forward<Args>(args)...
#else
-#define BOOST_UNORDERED_EMPLACE_ARGS1 create_emplace_args
-#define BOOST_UNORDERED_EMPLACE_ARGS2 create_emplace_args
-#define BOOST_UNORDERED_EMPLACE_ARGS3 create_emplace_args
-
#define BOOST_UNORDERED_EMPLACE_TEMPLATE typename Args
#define BOOST_UNORDERED_EMPLACE_ARGS Args const& args
#define BOOST_UNORDERED_EMPLACE_FORWARD args
@@ -491,7 +574,8 @@ template <typename T> T* const_cast_pointer(T const* x)
#endif
-template <typename A0> struct emplace_args1
+template <typename A0>
+struct emplace_args1
{
BOOST_UNORDERED_EARGS_MEMBER(1, 0, _)
@@ -568,8 +652,14 @@ inline emplace_args3<A0, A1, A2> create_emplace_args(
return e; \
}
+BOOST_UNORDERED_EARGS(1, 4, _)
+BOOST_UNORDERED_EARGS(1, 5, _)
+BOOST_UNORDERED_EARGS(1, 6, _)
+BOOST_UNORDERED_EARGS(1, 7, _)
+BOOST_UNORDERED_EARGS(1, 8, _)
+BOOST_UNORDERED_EARGS(1, 9, _)
BOOST_PP_REPEAT_FROM_TO(
- 4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS, _)
+ 10, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT), BOOST_UNORDERED_EARGS, _)
#undef BOOST_UNORDERED_DEFINE_EMPLACE_ARGS
#undef BOOST_UNORDERED_EARGS_MEMBER
@@ -738,13 +828,6 @@ template <typename T> struct identity
#include <boost/pointer_to_other.hpp>
#include <boost/utility/enable_if.hpp>
-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
- !defined(BOOST_NO_SFINAE_EXPR)
-#define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
-#else
-#define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
-#endif
-
namespace boost {
namespace unordered {
namespace detail {
@@ -1013,7 +1096,7 @@ template <typename Alloc> struct allocator_traits
}
public:
-#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
+#if BOOST_UNORDERED_CXX11_CONSTRUCTION
template <typename T, typename... Args>
static typename boost::enable_if_c<
@@ -1168,8 +1251,6 @@ template <typename Alloc> struct allocator_traits
#include <memory>
-#define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
-
namespace boost {
namespace unordered {
namespace detail {
@@ -1195,8 +1276,6 @@ template <typename Alloc, typename T> struct rebind_wrap
#include <boost/container/allocator_traits.hpp>
-#define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
-
namespace boost {
namespace unordered {
namespace detail {
@@ -1231,157 +1310,160 @@ namespace detail {
namespace func {
////////////////////////////////////////////////////////////////////////////
-// call_construct
+// construct_value
+//
+// Only use allocator_traits::construct, allocator_traits::destroy when full
+// C++11 support is available.
-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#if BOOST_UNORDERED_CXX11_CONSTRUCTION
-#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
+#define BOOST_UNORDERED_CALL_CONSTRUCT1(Traits, alloc, address, a0) \
+ Traits::construct(alloc, address, a0)
+#define BOOST_UNORDERED_CALL_DESTROY(Traits, alloc, x) Traits::destroy(alloc, x)
-template <typename Alloc, typename T, typename... Args>
-inline void call_construct(
- Alloc& alloc, T* address, BOOST_FWD_REF(Args)... args)
-{
- boost::unordered::detail::allocator_traits<Alloc>::construct(
- alloc, address, boost::forward<Args>(args)...);
-}
-
-template <typename Alloc, typename T>
-inline void call_destroy(Alloc& alloc, T* x)
-{
- boost::unordered::detail::allocator_traits<Alloc>::destroy(alloc, x);
-}
-
-#else
+#elif !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
-template <typename Alloc, typename T, typename... Args>
-inline void call_construct(Alloc&, T* address, BOOST_FWD_REF(Args)... args)
+template <typename T, typename... Args>
+inline void construct_value(T* address, BOOST_FWD_REF(Args)... args)
{
new ((void*)address) T(boost::forward<Args>(args)...);
}
-template <typename Alloc, typename T> inline void call_destroy(Alloc&, T* x)
-{
- boost::unordered::detail::func::destroy(x);
-}
-
-#endif
+#define BOOST_UNORDERED_CALL_CONSTRUCT1(Traits, alloc, address, a0) \
+ boost::unordered::detail::func::construct_value(address, a0)
+#define BOOST_UNORDERED_CALL_DESTROY(Traits, alloc, x) \
+ boost::unordered::detail::func::destroy(x)
#else
-template <typename Alloc, typename T>
-inline void call_construct(Alloc&, T* address)
+
+template <typename T> inline void construct_value(T* address)
{
new ((void*)address) T();
}
-template <typename Alloc, typename T, typename A0>
-inline void call_construct(Alloc&, T* address, BOOST_FWD_REF(A0) a0)
+template <typename T, typename A0>
+inline void construct_value(T* address, BOOST_FWD_REF(A0) a0)
{
new ((void*)address) T(boost::forward<A0>(a0));
}
-template <typename Alloc, typename T> inline void call_destroy(Alloc&, T* x)
-{
- boost::unordered::detail::func::destroy(x);
-}
+#define BOOST_UNORDERED_CALL_CONSTRUCT1(Traits, alloc, address, a0) \
+ boost::unordered::detail::func::construct_value(address, a0)
+#define BOOST_UNORDERED_CALL_DESTROY(Traits, alloc, x) \
+ boost::unordered::detail::func::destroy(x)
#endif
////////////////////////////////////////////////////////////////////////////
// Construct from tuple
//
-// Used for piecewise construction.
-
-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
-
-#define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
- template <typename Alloc, typename T> \
- void construct_from_tuple(Alloc& alloc, T* ptr, namespace_ tuple<>) \
- { \
- boost::unordered::detail::func::call_construct(alloc, ptr); \
- } \
- \
- BOOST_PP_REPEAT_FROM_TO( \
- 1, n, BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
+// Used to emulate piecewise construction.
-#define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
+#define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(z, n, namespace_) \
template <typename Alloc, typename T, \
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
- void construct_from_tuple(Alloc& alloc, T* ptr, \
- namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
+ void construct_from_tuple(Alloc&, T* ptr, \
+ namespace_::tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
{ \
- boost::unordered::detail::func::call_construct(alloc, ptr, \
+ new ((void*)ptr) T( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_)); \
}
-#define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) namespace_ get<n>(x)
+#define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) namespace_::get<n>(x)
-#elif !defined(__SUNPRO_CC)
+// construct_from_tuple for boost::tuple
+// The workaround for old Sun compilers comes later in the file.
-#define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
- template <typename Alloc, typename T> \
- void construct_from_tuple(Alloc&, T* ptr, namespace_ tuple<>) \
- { \
- new ((void*)ptr) T(); \
- } \
- \
- BOOST_PP_REPEAT_FROM_TO( \
- 1, n, BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
+#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
-#define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
- template <typename Alloc, typename T, \
- BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
- void construct_from_tuple(Alloc&, T* ptr, \
- namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
- { \
- new ((void*)ptr) T( \
- BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_)); \
- }
+template <typename Alloc, typename T>
+void construct_from_tuple(Alloc&, T* ptr, boost::tuple<>)
+{
+ new ((void*)ptr) T();
+}
-#define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) namespace_ get<n>(x)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 1, boost)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 2, boost)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 3, boost)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 4, boost)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 5, boost)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 6, boost)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 7, boost)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 8, boost)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 9, boost)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 10, boost)
-#else
+#endif
+
+// construct_from_tuple for std::tuple
+
+#if !BOOST_UNORDERED_CXX11_CONSTRUCTION && BOOST_UNORDERED_TUPLE_ARGS
+
+template <typename Alloc, typename T>
+void construct_from_tuple(Alloc&, T* ptr, std::tuple<>)
+{
+ new ((void*)ptr) T();
+}
+
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 1, std)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 2, std)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 3, std)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 4, std)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 5, std)
+
+#if BOOST_UNORDERED_TUPLE_ARGS >= 6
+BOOST_PP_REPEAT_FROM_TO(6, BOOST_PP_INC(BOOST_UNORDERED_TUPLE_ARGS),
+ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE, std)
+#endif
+
+#endif
+
+#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
+#undef BOOST_UNORDERED_GET_TUPLE_ARG
+
+// construct_from_tuple for boost::tuple on old versions of sunpro.
+//
+// Old versions of Sun C++ had problems with template overloads of
+// boost::tuple, so to fix it I added a distinct type for each length to
+// the overloads. That means there's no possible ambiguity between the
+// different overloads, so that the compiler doesn't get confused
+
+#if BOOST_UNORDERED_SUN_WORKAROUNDS1
template <int N> struct length
{
};
-#define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
- template <typename Alloc, typename T> \
- void construct_from_tuple_impl(boost::unordered::detail::func::length<0>, \
- Alloc&, T* ptr, namespace_ tuple<>) \
- { \
- new ((void*)ptr) T(); \
- } \
- \
- BOOST_PP_REPEAT_FROM_TO( \
- 1, n, BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
-
-#define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
+#define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(z, n, namespace_) \
template <typename Alloc, typename T, \
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
void construct_from_tuple_impl(boost::unordered::detail::func::length<n>, \
Alloc&, T* ptr, \
- namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
+ namespace_::tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
{ \
new ((void*)ptr) T( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_)); \
}
-#define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) namespace_ get<n>(x)
-
-#endif
-
-BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
-
-#if !defined(__SUNPRO_CC) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
-BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std::)
-#endif
+#define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) namespace_::get<n>(x)
-#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
-#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL
-#undef BOOST_UNORDERED_GET_TUPLE_ARG
+template <typename Alloc, typename T>
+void construct_from_tuple_impl(
+ boost::unordered::detail::func::length<0>, Alloc&, T* ptr, boost::tuple<>)
+{
+ new ((void*)ptr) T();
+}
-#if defined(__SUNPRO_CC)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 1, boost)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 2, boost)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 3, boost)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 4, boost)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 5, boost)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 6, boost)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 7, boost)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 8, boost)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 9, boost)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 10, boost)
template <typename Alloc, typename T, typename Tuple>
void construct_from_tuple(Alloc& alloc, T* ptr, Tuple const& x)
@@ -1391,6 +1473,9 @@ void construct_from_tuple(Alloc& alloc, T* ptr, Tuple const& x)
alloc, ptr, x);
}
+#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
+#undef BOOST_UNORDERED_GET_TUPLE_ARG
+
#endif
////////////////////////////////////////////////////////////////////////////
@@ -1409,25 +1494,77 @@ template <typename A0> struct use_piecewise
};
};
-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#if BOOST_UNORDERED_CXX11_CONSTRUCTION
////////////////////////////////////////////////////////////////////////////
// Construct from variadic parameters
-// For the standard pair constructor.
-
template <typename Alloc, typename T, typename... Args>
inline void construct_from_args(
Alloc& alloc, T* address, BOOST_FWD_REF(Args)... args)
{
- boost::unordered::detail::func::call_construct(
+ boost::unordered::detail::allocator_traits<Alloc>::construct(
alloc, address, boost::forward<Args>(args)...);
}
-// Special case for piece_construct
-//
-// TODO: When possible, it might be better to use std::pair's
-// constructor for std::piece_construct with std::tuple.
+// For backwards compatibility, implement a special case for
+// piecewise_construct with boost::tuple
+
+template <typename A0> struct detect_boost_tuple
+{
+ template <typename T0, typename T1, typename T2, typename T3, typename T4,
+ typename T5, typename T6, typename T7, typename T8, typename T9>
+ static choice1::type test(
+ choice1, boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> const&);
+
+ static choice2::type test(choice2, ...);
+
+ enum
+ {
+ value = sizeof(choice1::type) ==
+ sizeof(test(choose(), boost::unordered::detail::make<A0>()))
+ };
+};
+
+// Special case for piecewise_construct
+
+template <typename Alloc, typename A, typename B, typename A0, typename A1,
+ typename A2>
+inline typename boost::enable_if_c<use_piecewise<A0>::value &&
+ detect_boost_tuple<A1>::value &&
+ detect_boost_tuple<A2>::value,
+ void>::type
+construct_from_args(Alloc& alloc, std::pair<A, B>* address, BOOST_FWD_REF(A0),
+ BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
+{
+ boost::unordered::detail::func::construct_from_tuple(
+ alloc, boost::addressof(address->first), boost::forward<A1>(a1));
+ BOOST_TRY
+ {
+ boost::unordered::detail::func::construct_from_tuple(
+ alloc, boost::addressof(address->second), boost::forward<A2>(a2));
+ }
+ BOOST_CATCH(...)
+ {
+ boost::unordered::detail::func::destroy(
+ boost::addressof(address->first));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+}
+
+#elif !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+////////////////////////////////////////////////////////////////////////////
+// Construct from variadic parameters
+
+template <typename Alloc, typename T, typename... Args>
+inline void construct_from_args(Alloc&, T* address, BOOST_FWD_REF(Args)... args)
+{
+ new ((void*)address) T(boost::forward<Args>(args)...);
+}
+
+// Special case for piecewise_construct
template <typename Alloc, typename A, typename B, typename A0, typename A1,
typename A2>
@@ -1436,22 +1573,17 @@ inline typename enable_if<use_piecewise<A0>, void>::type construct_from_args(
BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
boost::unordered::detail::func::construct_from_tuple(
- alloc, boost::unordered::detail::func::const_cast_pointer(
- boost::addressof(address->first)),
- boost::forward<A1>(a1));
+ alloc, boost::addressof(address->first), boost::forward<A1>(a1));
BOOST_TRY
{
boost::unordered::detail::func::construct_from_tuple(
- alloc, boost::unordered::detail::func::const_cast_pointer(
- boost::addressof(address->second)),
- boost::forward<A2>(a2));
+ alloc, boost::addressof(address->second), boost::forward<A2>(a2));
}
BOOST_CATCH(...)
{
- boost::unordered::detail::func::call_destroy(
- alloc, boost::unordered::detail::func::const_cast_pointer(
- boost::addressof(address->first)));
- BOOST_RETHROW;
+ boost::unordered::detail::func::destroy(
+ boost::addressof(address->first));
+ BOOST_RETHROW
}
BOOST_CATCH_END
}
@@ -1500,12 +1632,18 @@ inline void construct_from_args(
num_params, BOOST_UNORDERED_CALL_FORWARD, args.a)); \
}
-BOOST_PP_REPEAT_FROM_TO(
- 4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_CONSTRUCT_IMPL, _)
+BOOST_UNORDERED_CONSTRUCT_IMPL(1, 4, _)
+BOOST_UNORDERED_CONSTRUCT_IMPL(1, 5, _)
+BOOST_UNORDERED_CONSTRUCT_IMPL(1, 6, _)
+BOOST_UNORDERED_CONSTRUCT_IMPL(1, 7, _)
+BOOST_UNORDERED_CONSTRUCT_IMPL(1, 8, _)
+BOOST_UNORDERED_CONSTRUCT_IMPL(1, 9, _)
+BOOST_PP_REPEAT_FROM_TO(10, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT),
+ BOOST_UNORDERED_CONSTRUCT_IMPL, _)
#undef BOOST_UNORDERED_CONSTRUCT_IMPL
-// Construct with piece_construct
+// Construct with piecewise_construct
template <typename Alloc, typename A, typename B, typename A0, typename A1,
typename A2>
@@ -1514,22 +1652,17 @@ inline void construct_from_args(Alloc& alloc, std::pair<A, B>* address,
typename enable_if<use_piecewise<A0>, void*>::type = 0)
{
boost::unordered::detail::func::construct_from_tuple(
- alloc, boost::unordered::detail::func::const_cast_pointer(
- boost::addressof(address->first)),
- args.a1);
+ alloc, boost::addressof(address->first), args.a1);
BOOST_TRY
{
boost::unordered::detail::func::construct_from_tuple(
- alloc, boost::unordered::detail::func::const_cast_pointer(
- boost::addressof(address->second)),
- args.a2);
+ alloc, boost::addressof(address->second), args.a2);
}
BOOST_CATCH(...)
{
- boost::unordered::detail::func::call_destroy(
- alloc, boost::unordered::detail::func::const_cast_pointer(
- boost::addressof(address->first)));
- BOOST_RETHROW;
+ boost::unordered::detail::func::destroy(
+ boost::addressof(address->first));
+ BOOST_RETHROW
}
BOOST_CATCH_END
}
@@ -1559,12 +1692,8 @@ template <typename NodeAlloc> struct node_constructor
node_allocator& alloc_;
node_pointer node_;
- bool node_constructed_;
- node_constructor(node_allocator& n)
- : alloc_(n), node_(), node_constructed_(false)
- {
- }
+ node_constructor(node_allocator& n) : alloc_(n), node_() {}
~node_constructor();
@@ -1573,7 +1702,7 @@ template <typename NodeAlloc> struct node_constructor
// no throw
node_pointer release()
{
- BOOST_ASSERT(node_ && node_constructed_);
+ BOOST_ASSERT(node_);
node_pointer p = node_;
node_ = node_pointer();
return p;
@@ -1583,9 +1712,8 @@ template <typename NodeAlloc> struct node_constructor
{
BOOST_ASSERT(!node_);
node_ = p;
- node_constructed_ = true;
- boost::unordered::detail::func::call_destroy(
- alloc_, node_->value_ptr());
+ BOOST_UNORDERED_CALL_DESTROY(
+ node_allocator_traits, alloc_, node_->value_ptr());
}
private:
@@ -1596,10 +1724,7 @@ template <typename NodeAlloc> struct node_constructor
template <typename Alloc> node_constructor<Alloc>::~node_constructor()
{
if (node_) {
- if (node_constructed_) {
- boost::unordered::detail::func::destroy(boost::addressof(*node_));
- }
-
+ boost::unordered::detail::func::destroy(pointer<node>::get(node_));
node_allocator_traits::deallocate(alloc_, node_, 1);
}
}
@@ -1607,13 +1732,8 @@ template <typename Alloc> node_constructor<Alloc>::~node_constructor()
template <typename Alloc> void node_constructor<Alloc>::create_node()
{
BOOST_ASSERT(!node_);
- node_constructed_ = false;
-
node_ = node_allocator_traits::allocate(alloc_, 1);
-
- new ((void*)boost::addressof(*node_)) node();
- node_->init(node_);
- node_constructed_ = true;
+ new (pointer<void>::get(node_)) node();
}
template <typename NodeAlloc> struct node_tmp
@@ -1621,6 +1741,7 @@ template <typename NodeAlloc> struct node_tmp
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
node_allocator_traits;
typedef typename node_allocator_traits::pointer node_pointer;
+ typedef typename node_allocator_traits::value_type node;
NodeAlloc& alloc_;
node_pointer node_;
@@ -1641,9 +1762,9 @@ template <typename NodeAlloc> struct node_tmp
template <typename Alloc> node_tmp<Alloc>::~node_tmp()
{
if (node_) {
- boost::unordered::detail::func::call_destroy(
- alloc_, node_->value_ptr());
- boost::unordered::detail::func::destroy(boost::addressof(*node_));
+ BOOST_UNORDERED_CALL_DESTROY(
+ node_allocator_traits, alloc_, node_->value_ptr());
+ boost::unordered::detail::func::destroy(pointer<node>::get(node_));
node_allocator_traits::deallocate(alloc_, node_, 1);
}
}
@@ -1676,35 +1797,84 @@ construct_node(Alloc& alloc, BOOST_FWD_REF(U) x)
{
node_constructor<Alloc> a(alloc);
a.create_node();
- boost::unordered::detail::func::call_construct(
- alloc, a.node_->value_ptr(), boost::forward<U>(x));
+ BOOST_UNORDERED_CALL_CONSTRUCT1(
+ boost::unordered::detail::allocator_traits<Alloc>, alloc,
+ a.node_->value_ptr(), boost::forward<U>(x));
+ return a.release();
+}
+
+#if BOOST_UNORDERED_CXX11_CONSTRUCTION
+
+template <typename Alloc, typename Key>
+inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
+construct_node_pair(Alloc& alloc, BOOST_FWD_REF(Key) k)
+{
+ node_constructor<Alloc> a(alloc);
+ a.create_node();
+ boost::unordered::detail::allocator_traits<Alloc>::construct(alloc,
+ a.node_->value_ptr(), std::piecewise_construct,
+ std::forward_as_tuple(boost::forward<Key>(k)), std::forward_as_tuple());
+ return a.release();
+}
+
+template <typename Alloc, typename Key, typename Mapped>
+inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
+construct_node_pair(Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Mapped) m)
+{
+ node_constructor<Alloc> a(alloc);
+ a.create_node();
+ boost::unordered::detail::allocator_traits<Alloc>::construct(alloc,
+ a.node_->value_ptr(), std::piecewise_construct,
+ std::forward_as_tuple(boost::forward<Key>(k)),
+ std::forward_as_tuple(boost::forward<Mapped>(m)));
+ return a.release();
+}
+
+template <typename Alloc, typename Key, typename... Args>
+inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
+construct_node_pair_from_args(
+ Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Args)... args)
+{
+ node_constructor<Alloc> a(alloc);
+ a.create_node();
+#if !(BOOST_COMP_CLANG && BOOST_COMP_CLANG < BOOST_VERSION_NUMBER(3, 8, 0) && \
+ defined(BOOST_LIBSTDCXX11))
+ boost::unordered::detail::allocator_traits<Alloc>::construct(alloc,
+ a.node_->value_ptr(), std::piecewise_construct,
+ std::forward_as_tuple(boost::forward<Key>(k)),
+ std::forward_as_tuple(boost::forward<Args>(args)...));
+#else
+ // It doesn't seem to be possible to construct a tuple with 3 variadic
+ // rvalue reference members when using older versions of clang with
+ // libstdc++, so just use std::make_tuple instead of std::forward_as_tuple.
+ boost::unordered::detail::allocator_traits<Alloc>::construct(alloc,
+ a.node_->value_ptr(), std::piecewise_construct,
+ std::forward_as_tuple(boost::forward<Key>(k)),
+ std::make_tuple(boost::forward<Args>(args)...));
+#endif
return a.release();
}
-// TODO: When possible, it might be better to use std::pair's
-// constructor for std::piece_construct with std::tuple.
+#else
+
template <typename Alloc, typename Key>
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
construct_node_pair(Alloc& alloc, BOOST_FWD_REF(Key) k)
{
node_constructor<Alloc> a(alloc);
a.create_node();
- boost::unordered::detail::func::call_construct(
- alloc, boost::unordered::detail::func::const_cast_pointer(
- boost::addressof(a.node_->value_ptr()->first)),
- boost::forward<Key>(k));
+ boost::unordered::detail::func::construct_value(
+ boost::addressof(a.node_->value_ptr()->first), boost::forward<Key>(k));
BOOST_TRY
{
- boost::unordered::detail::func::call_construct(
- alloc, boost::unordered::detail::func::const_cast_pointer(
- boost::addressof(a.node_->value_ptr()->second)));
+ boost::unordered::detail::func::construct_value(
+ boost::addressof(a.node_->value_ptr()->second));
}
BOOST_CATCH(...)
{
- boost::unordered::detail::func::call_destroy(
- alloc, boost::unordered::detail::func::const_cast_pointer(
- boost::addressof(a.node_->value_ptr()->first)));
- BOOST_RETHROW;
+ boost::unordered::detail::func::destroy(
+ boost::addressof(a.node_->value_ptr()->first));
+ BOOST_RETHROW
}
BOOST_CATCH_END
return a.release();
@@ -1716,23 +1886,19 @@ construct_node_pair(Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Mapped) m)
{
node_constructor<Alloc> a(alloc);
a.create_node();
- boost::unordered::detail::func::call_construct(
- alloc, boost::unordered::detail::func::const_cast_pointer(
- boost::addressof(a.node_->value_ptr()->first)),
- boost::forward<Key>(k));
+ boost::unordered::detail::func::construct_value(
+ boost::addressof(a.node_->value_ptr()->first), boost::forward<Key>(k));
BOOST_TRY
{
- boost::unordered::detail::func::call_construct(
- alloc, boost::unordered::detail::func::const_cast_pointer(
- boost::addressof(a.node_->value_ptr()->second)),
+ boost::unordered::detail::func::construct_value(
+ boost::addressof(a.node_->value_ptr()->second),
boost::forward<Mapped>(m));
}
BOOST_CATCH(...)
{
- boost::unordered::detail::func::call_destroy(
- alloc, boost::unordered::detail::func::const_cast_pointer(
- boost::addressof(a.node_->value_ptr()->first)));
- BOOST_RETHROW;
+ boost::unordered::detail::func::destroy(
+ boost::addressof(a.node_->value_ptr()->first));
+ BOOST_RETHROW
}
BOOST_CATCH_END
return a.release();
@@ -1745,27 +1911,25 @@ construct_node_pair_from_args(
{
node_constructor<Alloc> a(alloc);
a.create_node();
- boost::unordered::detail::func::call_construct(
- alloc, boost::unordered::detail::func::const_cast_pointer(
- boost::addressof(a.node_->value_ptr()->first)),
- boost::forward<Key>(k));
+ boost::unordered::detail::func::construct_value(
+ boost::addressof(a.node_->value_ptr()->first), boost::forward<Key>(k));
BOOST_TRY
{
- boost::unordered::detail::func::construct_from_args(
- alloc, boost::unordered::detail::func::const_cast_pointer(
- boost::addressof(a.node_->value_ptr()->second)),
+ boost::unordered::detail::func::construct_from_args(alloc,
+ boost::addressof(a.node_->value_ptr()->second),
BOOST_UNORDERED_EMPLACE_FORWARD);
}
BOOST_CATCH(...)
{
- boost::unordered::detail::func::call_destroy(
- alloc, boost::unordered::detail::func::const_cast_pointer(
- boost::addressof(a.node_->value_ptr()->first)));
- BOOST_RETHROW;
+ boost::unordered::detail::func::destroy(
+ boost::addressof(a.node_->value_ptr()->first));
+ BOOST_RETHROW
}
BOOST_CATCH_END
return a.release();
}
+
+#endif
}
}
}
@@ -1788,13 +1952,13 @@ namespace iterator_detail {
//
// all no throw
-template <typename Node, typename Policy>
+template <typename Node>
struct l_iterator : public std::iterator<std::forward_iterator_tag,
typename Node::value_type, std::ptrdiff_t,
typename Node::value_type*, typename Node::value_type&>
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
- template <typename Node2, typename Policy2>
+ template <typename Node2>
friend struct boost::unordered::iterator_detail::cl_iterator;
private:
@@ -1823,7 +1987,7 @@ struct l_iterator : public std::iterator<std::forward_iterator_tag,
l_iterator& operator++()
{
ptr_ = static_cast<node_pointer>(ptr_->next_);
- if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_) != bucket_)
+ if (ptr_ && ptr_->get_bucket() != bucket_)
ptr_ = node_pointer();
return *this;
}
@@ -1846,13 +2010,13 @@ struct l_iterator : public std::iterator<std::forward_iterator_tag,
}
};
-template <typename Node, typename Policy>
+template <typename Node>
struct cl_iterator
: public std::iterator<std::forward_iterator_tag, typename Node::value_type,
std::ptrdiff_t, typename Node::value_type const*,
typename Node::value_type const&>
{
- friend struct boost::unordered::iterator_detail::l_iterator<Node, Policy>;
+ friend struct boost::unordered::iterator_detail::l_iterator<Node>;
private:
typedef typename Node::node_pointer node_pointer;
@@ -1872,8 +2036,7 @@ struct cl_iterator
{
}
- cl_iterator(
- boost::unordered::iterator_detail::l_iterator<Node, Policy> const& x)
+ cl_iterator(boost::unordered::iterator_detail::l_iterator<Node> const& x)
BOOST_NOEXCEPT : ptr_(x.ptr_),
bucket_(x.bucket_),
bucket_count_(x.bucket_count_)
@@ -1887,7 +2050,7 @@ struct cl_iterator
cl_iterator& operator++()
{
ptr_ = static_cast<node_pointer>(ptr_->next_);
- if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_) != bucket_)
+ if (ptr_ && ptr_->get_bucket() != bucket_)
ptr_ = node_pointer();
return *this;
}
@@ -1921,9 +2084,6 @@ struct iterator : public std::iterator<std::forward_iterator_tag,
template <typename>
friend struct boost::unordered::iterator_detail::c_iterator;
template <typename> friend struct boost::unordered::detail::table;
- template <typename> friend struct boost::unordered::detail::table_impl;
- template <typename>
- friend struct boost::unordered::detail::grouped_table_impl;
private:
#endif
@@ -1978,9 +2138,6 @@ struct c_iterator
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename> friend struct boost::unordered::detail::table;
- template <typename> friend struct boost::unordered::detail::table_impl;
- template <typename>
- friend struct boost::unordered::detail::grouped_table_impl;
private:
#endif
@@ -2076,7 +2233,6 @@ template <typename NodeAlloc> struct node_holder
{
node_pointer n = nodes_;
nodes_ = static_cast<node_pointer>(nodes_->next_);
- n->init(n);
n->next_ = link_pointer();
return n;
}
@@ -2088,7 +2244,7 @@ template <typename NodeAlloc> struct node_holder
} else {
constructor_.create_node();
}
- boost::unordered::detail::func::call_construct(
+ BOOST_UNORDERED_CALL_CONSTRUCT1(node_allocator_traits,
constructor_.alloc_, constructor_.node_->value_ptr(), v);
return constructor_.release();
}
@@ -2100,8 +2256,9 @@ template <typename NodeAlloc> struct node_holder
} else {
constructor_.create_node();
}
- boost::unordered::detail::func::call_construct(constructor_.alloc_,
- constructor_.node_->value_ptr(), boost::move(v));
+ BOOST_UNORDERED_CALL_CONSTRUCT1(node_allocator_traits,
+ constructor_.alloc_, constructor_.node_->value_ptr(),
+ boost::move(v));
return constructor_.release();
}
@@ -2114,9 +2271,9 @@ template <typename Alloc> node_holder<Alloc>::~node_holder()
node_pointer p = nodes_;
nodes_ = static_cast<node_pointer>(p->next_);
- boost::unordered::detail::func::call_destroy(
- constructor_.alloc_, p->value_ptr());
- boost::unordered::detail::func::destroy(boost::addressof(*p));
+ BOOST_UNORDERED_CALL_DESTROY(
+ node_allocator_traits, constructor_.alloc_, p->value_ptr());
+ boost::unordered::detail::func::destroy(pointer<node>::get(p));
node_allocator_traits::deallocate(constructor_.alloc_, p, 1);
}
}
@@ -2131,6 +2288,7 @@ template <typename NodePointer> struct bucket
link_pointer next_;
bucket() : next_() {}
+ bucket(link_pointer n) : next_(n) {}
link_pointer first_from_start() { return next_; }
@@ -2146,6 +2304,7 @@ struct ptr_bucket
link_pointer next_;
ptr_bucket() : next_(0) {}
+ ptr_bucket(link_pointer n) : next_(n) {}
link_pointer first_from_start() { return this; }
@@ -2332,13 +2491,13 @@ template <class H, class P> class functions
function_pair const& current() const
{
return *static_cast<function_pair const*>(
- static_cast<void const*>(&funcs_[current_]));
+ static_cast<void const*>(funcs_[current_].address()));
}
function_pair& current()
{
return *static_cast<function_pair*>(
- static_cast<void*>(&funcs_[current_]));
+ static_cast<void*>(funcs_[current_].address()));
}
void construct(bool which, H const& hf, P const& eq)
@@ -2549,7 +2708,6 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
typedef typename Types::c_iterator c_iterator;
typedef typename Types::l_iterator l_iterator;
typedef typename Types::cl_iterator cl_iterator;
- typedef typename Types::node_algo node_algo;
typedef boost::unordered::detail::functions<typename Types::hasher,
typename Types::key_equal>
@@ -2572,6 +2730,8 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
node_constructor;
typedef boost::unordered::detail::node_tmp<node_allocator> node_tmp;
+ typedef std::pair<iterator, bool> emplace_return;
+
////////////////////////////////////////////////////////////////////////
// Members
@@ -2586,6 +2746,45 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
////////////////////////////////////////////////////////////////////////
// Data access
+ static node_pointer get_node(c_iterator it) { return it.node_; }
+
+ static node_pointer next_node(link_pointer n)
+ {
+ return static_cast<node_pointer>(n->next_);
+ }
+
+ static node_pointer next_for_find(link_pointer n)
+ {
+ node_pointer n2 = static_cast<node_pointer>(n);
+ do {
+ n2 = next_node(n2);
+ } while (n2 && !n2->is_first_in_group());
+ return n2;
+ }
+
+ node_pointer next_group(node_pointer n) const
+ {
+ node_pointer n1 = n;
+ do {
+ n1 = next_node(n1);
+ } while (n1 && !n1->is_first_in_group());
+ return n1;
+ }
+
+ std::size_t group_count(node_pointer n) const
+ {
+ std::size_t x = 0;
+ node_pointer it = n;
+ do {
+ ++x;
+ it = next_node(it);
+ } while (it && !it->is_first_in_group());
+
+ return x;
+ }
+
+ std::size_t node_bucket(node_pointer n) const { return n->get_bucket(); }
+
bucket_allocator const& bucket_alloc() const { return allocators_.first(); }
node_allocator const& node_alloc() const { return allocators_.second(); }
@@ -2619,8 +2818,7 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
node_pointer begin() const
{
- return size_ ? node_algo::next_node(get_previous_start())
- : node_pointer();
+ return size_ ? next_node(get_previous_start()) : node_pointer();
}
node_pointer begin(std::size_t bucket_index) const
@@ -2628,7 +2826,7 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
if (!size_)
return node_pointer();
link_pointer prev = get_previous_start(bucket_index);
- return prev ? node_algo::next_node(prev) : node_pointer();
+ return prev ? next_node(prev) : node_pointer();
}
std::size_t hash_to_bucket(std::size_t hash_value) const
@@ -2636,12 +2834,6 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
return policy::to_bucket(bucket_count_, hash_value);
}
- float load_factor() const
- {
- BOOST_ASSERT(bucket_count_ != 0);
- return static_cast<float>(size_) / static_cast<float>(bucket_count_);
- }
-
std::size_t bucket_size(std::size_t index) const
{
node_pointer n = begin(index);
@@ -2649,9 +2841,9 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
return 0;
std::size_t count = 0;
- while (n && hash_to_bucket(n->hash_) == index) {
+ while (n && node_bucket(n) == index) {
++count;
- n = node_algo::next_node(n);
+ n = next_node(n);
}
return count;
@@ -2660,17 +2852,6 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
////////////////////////////////////////////////////////////////////////
// Load methods
- std::size_t max_size() const
- {
- using namespace std;
-
- // size < mlf_ * count
- return boost::unordered::detail::double_to_size(
- ceil(static_cast<double>(mlf_) *
- static_cast<double>(max_bucket_count()))) -
- 1;
- }
-
void recalculate_max_load()
{
using namespace std;
@@ -2742,79 +2923,68 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
table(
table& x, node_allocator const& a, boost::unordered::detail::move_tag m)
: functions(x, m), allocators_(a, a), bucket_count_(x.bucket_count_),
- size_(0), mlf_(x.mlf_), max_load_(x.max_load_), buckets_()
+ size_(0), mlf_(x.mlf_), max_load_(0), buckets_()
{
}
////////////////////////////////////////////////////////////////////////
- // Initialisation.
-
- void init(table const& x)
- {
- if (x.size_) {
- static_cast<table_impl*>(this)->copy_buckets(x);
- }
- }
-
- void move_init(table& x)
+ // Clear buckets and Create buckets
+ //
+ // IMPORTANT: If the container already contains any elements, the
+ // buckets will not contain any links to them. This will
+ // need to be dealt with, for example by:
+ // - deleting them
+ // - putting them in a 'node_holder' for future use
+ // (as in assignment)
+ // - placing them in buckets (see rehash_impl)
+
+ // Clear the bucket pointers.
+ void clear_buckets()
{
- if (node_alloc() == x.node_alloc()) {
- move_buckets_from(x);
- } else if (x.size_) {
- // TODO: Could pick new bucket size?
- static_cast<table_impl*>(this)->move_buckets(x);
+ bucket_pointer end = get_bucket(bucket_count_);
+ for (bucket_pointer it = buckets_; it != end; ++it) {
+ it->next_ = node_pointer();
}
}
- ////////////////////////////////////////////////////////////////////////
- // Create buckets
-
+ // Create container buckets. If the container already contains any buckets
+ // the linked list will be transferred to the new buckets, but none
+ // of the bucket pointers will be set. See above note.
+ //
+ // Strong exception safety.
void create_buckets(std::size_t new_count)
{
- std::size_t length = new_count + 1;
- bucket_pointer new_buckets =
- bucket_allocator_traits::allocate(bucket_alloc(), length);
- bucket_pointer constructed = new_buckets;
-
- BOOST_TRY
- {
- bucket_pointer end =
- new_buckets + static_cast<std::ptrdiff_t>(length);
- for (; constructed != end; ++constructed) {
- new ((void*)boost::addressof(*constructed)) bucket();
- }
-
- if (buckets_) {
- // Copy the nodes to the new buckets, including the dummy
- // node if there is one.
- (new_buckets + static_cast<std::ptrdiff_t>(new_count))->next_ =
- (buckets_ + static_cast<std::ptrdiff_t>(bucket_count_))
- ->next_;
- destroy_buckets();
- } else if (bucket::extra_node) {
- node_constructor a(node_alloc());
- a.create_node();
-
- (new_buckets + static_cast<std::ptrdiff_t>(new_count))->next_ =
- a.release();
- }
- }
- BOOST_CATCH(...)
- {
- for (bucket_pointer p = new_buckets; p != constructed; ++p) {
- boost::unordered::detail::func::destroy(boost::addressof(*p));
- }
+ link_pointer dummy_node;
- bucket_allocator_traits::deallocate(
- bucket_alloc(), new_buckets, length);
-
- BOOST_RETHROW;
+ // Construct the new buckets and dummy node, and destroy the old buckets
+ if (buckets_) {
+ dummy_node =
+ (buckets_ + static_cast<std::ptrdiff_t>(bucket_count_))->next_;
+ bucket_pointer new_buckets = bucket_allocator_traits::allocate(
+ bucket_alloc(), new_count + 1);
+ destroy_buckets();
+ buckets_ = new_buckets;
+ } else if (bucket::extra_node) {
+ node_constructor a(node_alloc());
+ a.create_node();
+ buckets_ = bucket_allocator_traits::allocate(
+ bucket_alloc(), new_count + 1);
+ dummy_node = a.release();
+ } else {
+ dummy_node = link_pointer();
+ buckets_ = bucket_allocator_traits::allocate(
+ bucket_alloc(), new_count + 1);
}
- BOOST_CATCH_END
+ // nothrow from here...
bucket_count_ = new_count;
- buckets_ = new_buckets;
recalculate_max_load();
+
+ bucket_pointer end = buckets_ + static_cast<std::ptrdiff_t>(new_count);
+ for (bucket_pointer i = buckets_; i != end; ++i) {
+ new (pointer<void>::get(i)) bucket();
+ }
+ new (pointer<void>::get(end)) bucket(dummy_node);
}
////////////////////////////////////////////////////////////////////////
@@ -2865,6 +3035,7 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
buckets_ = other.buckets_;
bucket_count_ = other.bucket_count_;
size_ = other.size_;
+ max_load_ = other.max_load_;
other.buckets_ = bucket_pointer();
other.size_ = 0;
other.max_load_ = 0;
@@ -2875,69 +3046,37 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
~table() { delete_buckets(); }
- void delete_node(link_pointer prev)
+ void destroy_node(node_pointer n)
{
- node_pointer n = static_cast<node_pointer>(prev->next_);
- prev->next_ = n->next_;
-
- boost::unordered::detail::func::call_destroy(
- node_alloc(), n->value_ptr());
- boost::unordered::detail::func::destroy(boost::addressof(*n));
+ BOOST_UNORDERED_CALL_DESTROY(
+ node_allocator_traits, node_alloc(), n->value_ptr());
+ boost::unordered::detail::func::destroy(pointer<node>::get(n));
node_allocator_traits::deallocate(node_alloc(), n, 1);
- --size_;
- }
-
- std::size_t delete_nodes(link_pointer prev, link_pointer end)
- {
- BOOST_ASSERT(prev->next_ != end);
-
- std::size_t count = 0;
-
- do {
- delete_node(prev);
- ++count;
- } while (prev->next_ != end);
-
- return count;
}
void delete_buckets()
{
if (buckets_) {
- if (size_)
- delete_nodes(get_previous_start(), link_pointer());
+ node_pointer n =
+ static_cast<node_pointer>(get_bucket(bucket_count_)->next_);
if (bucket::extra_node) {
- node_pointer n =
- static_cast<node_pointer>(get_bucket(bucket_count_)->next_);
- boost::unordered::detail::func::destroy(boost::addressof(*n));
+ node_pointer next = next_node(n);
+ boost::unordered::detail::func::destroy(pointer<node>::get(n));
node_allocator_traits::deallocate(node_alloc(), n, 1);
+ n = next;
+ }
+
+ while (n) {
+ node_pointer next = next_node(n);
+ destroy_node(n);
+ n = next;
}
destroy_buckets();
buckets_ = bucket_pointer();
max_load_ = 0;
- }
-
- BOOST_ASSERT(!size_);
- }
-
- void clear()
- {
- if (!size_)
- return;
-
- delete_nodes(get_previous_start(), link_pointer());
- clear_buckets();
-
- BOOST_ASSERT(!size_);
- }
-
- void clear_buckets()
- {
- bucket_pointer end = get_bucket(bucket_count_);
- for (bucket_pointer it = buckets_; it != end; ++it) {
- it->next_ = node_pointer();
+ size_ = 0;
}
}
@@ -2945,7 +3084,7 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
{
bucket_pointer end = get_bucket(bucket_count_ + 1);
for (bucket_pointer it = buckets_; it != end; ++it) {
- boost::unordered::detail::func::destroy(boost::addressof(*it));
+ boost::unordered::detail::func::destroy(pointer<bucket>::get(it));
}
bucket_allocator_traits::deallocate(
@@ -2953,74 +3092,81 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
}
////////////////////////////////////////////////////////////////////////
- // Fix buckets after delete
+ // Fix buckets after delete/extract
//
+ // (prev,next) should mark an open range of nodes in a single bucket which
+ // have either been unlinked, or are about to be.
- std::size_t fix_bucket(std::size_t bucket_index, link_pointer prev)
+ std::size_t fix_bucket(
+ std::size_t bucket_index, link_pointer prev, node_pointer next)
{
- link_pointer end = prev->next_;
std::size_t bucket_index2 = bucket_index;
- if (end) {
- bucket_index2 =
- hash_to_bucket(static_cast<node_pointer>(end)->hash_);
+ if (next) {
+ bucket_index2 = node_bucket(next);
- // If begin and end are in the same bucket, then
- // there's nothing to do.
- if (bucket_index == bucket_index2)
+ // If next is in the same bucket, then there's nothing to do.
+ if (bucket_index == bucket_index2) {
return bucket_index2;
+ }
- // Update the bucket containing end.
+ // Update the bucket containing next.
get_bucket(bucket_index2)->next_ = prev;
}
// Check if this bucket is now empty.
bucket_pointer this_bucket = get_bucket(bucket_index);
- if (this_bucket->next_ == prev)
+ if (this_bucket->next_ == prev) {
this_bucket->next_ = link_pointer();
+ }
return bucket_index2;
}
////////////////////////////////////////////////////////////////////////
+ // Clear
+
+ void clear_impl();
+
+ ////////////////////////////////////////////////////////////////////////
// Assignment
- void assign(table const& x)
+ template <typename UniqueType>
+ void assign(table const& x, UniqueType is_unique)
{
- if (this != boost::addressof(x)) {
- assign(x, boost::unordered::detail::integral_constant<bool,
- allocator_traits<node_allocator>::
- propagate_on_container_copy_assignment::value>());
+ if (this != &x) {
+ assign(x, is_unique,
+ boost::unordered::detail::integral_constant<bool,
+ allocator_traits<node_allocator>::
+ propagate_on_container_copy_assignment::value>());
}
}
- void assign(table const& x, false_type)
+ template <typename UniqueType>
+ void assign(table const& x, UniqueType is_unique, false_type)
{
// Strong exception safety.
set_hash_functions new_func_this(*this, x);
mlf_ = x.mlf_;
recalculate_max_load();
- if (!size_ && !x.size_) {
- new_func_this.commit();
- return;
- }
-
if (x.size_ >= max_load_) {
create_buckets(min_buckets_for_size(x.size_));
- } else {
+ } else if (size_) {
clear_buckets();
}
new_func_this.commit();
- static_cast<table_impl*>(this)->assign_buckets(x);
+
+ assign_buckets(x, is_unique);
}
- void assign(table const& x, true_type)
+ template <typename UniqueType>
+ void assign(table const& x, UniqueType is_unique, true_type)
{
if (node_alloc() == x.node_alloc()) {
allocators_.assign(x.allocators_);
- assign(x, false_type());
+ assign(x, is_unique, false_type());
} else {
set_hash_functions new_func_this(*this, x);
@@ -3033,45 +3179,46 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
new_func_this.commit();
mlf_ = x.mlf_;
bucket_count_ = min_buckets_for_size(x.size_);
- max_load_ = 0;
// Finally copy the elements.
if (x.size_) {
- static_cast<table_impl*>(this)->copy_buckets(x);
+ copy_buckets(x, is_unique);
}
}
}
- void move_assign(table& x)
+ template <typename UniqueType>
+ void move_assign(table& x, UniqueType is_unique)
{
- if (this != boost::addressof(x)) {
+ if (this != &x) {
move_assign(
- x, boost::unordered::detail::integral_constant<bool,
- allocator_traits<node_allocator>::
- propagate_on_container_move_assignment::value>());
+ x, is_unique,
+ boost::unordered::detail::integral_constant<bool,
+ allocator_traits<node_allocator>::
+ propagate_on_container_move_assignment::value>());
}
}
- void move_assign(table& x, true_type)
+ template <typename UniqueType>
+ void move_assign(table& x, UniqueType, true_type)
{
delete_buckets();
set_hash_functions new_func_this(*this, x);
allocators_.move_assign(x.allocators_);
// No throw from here.
mlf_ = x.mlf_;
- max_load_ = x.max_load_;
move_buckets_from(x);
new_func_this.commit();
}
- void move_assign(table& x, false_type)
+ template <typename UniqueType>
+ void move_assign(table& x, UniqueType is_unique, false_type)
{
if (node_alloc() == x.node_alloc()) {
delete_buckets();
set_hash_functions new_func_this(*this, x);
// No throw from here.
mlf_ = x.mlf_;
- max_load_ = x.max_load_;
move_buckets_from(x);
new_func_this.commit();
} else {
@@ -3079,27 +3226,23 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
mlf_ = x.mlf_;
recalculate_max_load();
- if (!size_ && !x.size_) {
- new_func_this.commit();
- return;
- }
-
if (x.size_ >= max_load_) {
create_buckets(min_buckets_for_size(x.size_));
- } else {
+ } else if (size_) {
clear_buckets();
}
new_func_this.commit();
- static_cast<table_impl*>(this)->move_assign_buckets(x);
+
+ move_assign_buckets(x, is_unique);
}
}
// Accessors
- const_key_type& get_key(value_type const& x) const
+ const_key_type& get_key(node_pointer n) const
{
- return extractor::extract(x);
+ return extractor::extract(n->value());
}
std::size_t hash(const_key_type& k) const
@@ -3109,13 +3252,6 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
// Find Node
- template <typename Key, typename Hash, typename Pred>
- node_pointer generic_find_node(
- Key const& k, Hash const& hf, Pred const& eq) const
- {
- return this->find_node_impl(policy::apply_hash(hf, k), k, eq);
- }
-
node_pointer find_node(std::size_t key_hash, const_key_type& k) const
{
return this->find_node_impl(key_hash, k, this->key_eq());
@@ -3137,22 +3273,18 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
if (!n)
return n;
- std::size_t node_hash = n->hash_;
- if (key_hash == node_hash) {
- if (eq(k, this->get_key(n->value())))
- return n;
- } else {
- if (this->hash_to_bucket(node_hash) != bucket_index)
- return node_pointer();
+ if (eq(k, this->get_key(n))) {
+ return n;
+ } else if (this->node_bucket(n) != bucket_index) {
+ return node_pointer();
}
- n = node_algo::next_for_find(n);
+ n = next_for_find(n);
}
}
// Find the node before the key, so that it can be erased.
- link_pointer find_previous_node(
- const_key_type& k, std::size_t key_hash, std::size_t bucket_index)
+ link_pointer find_previous_node(const_key_type& k, std::size_t bucket_index)
{
link_pointer prev = this->get_previous_start(bucket_index);
if (!prev) {
@@ -3160,19 +3292,17 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
}
for (;;) {
- if (!prev->next_) {
+ node_pointer n = next_node(prev);
+ if (!n) {
return link_pointer();
+ } else if (n->is_first_in_group()) {
+ if (node_bucket(n) != bucket_index) {
+ return link_pointer();
+ } else if (this->key_eq()(k, this->get_key(n))) {
+ return prev;
+ }
}
- std::size_t node_hash = node_algo::next_node(prev)->hash_;
- if (this->hash_to_bucket(node_hash) != bucket_index) {
- return link_pointer();
- }
- if (node_hash == key_hash &&
- this->key_eq()(
- k, this->get_key(node_algo::next_node(prev)->value()))) {
- return prev;
- }
- prev = node_algo::next_for_erase(prev);
+ prev = n;
}
}
@@ -3185,13 +3315,18 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
}
std::size_t key_hash = this->hash(k);
std::size_t bucket_index = this->hash_to_bucket(key_hash);
- link_pointer prev = this->find_previous_node(k, key_hash, bucket_index);
+ link_pointer prev = this->find_previous_node(k, bucket_index);
if (!prev) {
return node_pointer();
}
- node_pointer n = node_algo::extract_first_node(prev);
+ node_pointer n = next_node(prev);
+ node_pointer n2 = next_node(n);
+ if (n2) {
+ n2->set_first_in_group();
+ }
+ prev->next_ = n2;
--this->size_;
- this->fix_bucket(bucket_index, prev);
+ this->fix_bucket(bucket_index, prev, n2);
n->next_ = link_pointer();
return n;
@@ -3203,502 +3338,19 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
void rehash(std::size_t);
void reserve(std::size_t);
void rehash_impl(std::size_t);
-};
-
-////////////////////////////////////////////////////////////////////////////
-// Reserve & Rehash
-
-// basic exception safety
-template <typename Types>
-inline void table<Types>::reserve_for_insert(std::size_t size)
-{
- if (!buckets_) {
- create_buckets((std::max)(bucket_count_, min_buckets_for_size(size)));
- } else if (size > max_load_) {
- std::size_t num_buckets =
- min_buckets_for_size((std::max)(size, size_ + (size_ >> 1)));
-
- if (num_buckets != bucket_count_)
- this->rehash_impl(num_buckets);
- }
-}
-
-// if hash function throws, basic exception safety
-// strong otherwise.
-
-template <typename Types>
-inline void table<Types>::rehash(std::size_t min_buckets)
-{
- using namespace std;
-
- if (!size_) {
- delete_buckets();
- bucket_count_ = policy::new_bucket_count(min_buckets);
- } else {
- min_buckets = policy::new_bucket_count((std::max)(min_buckets,
- boost::unordered::detail::double_to_size(
- floor(static_cast<double>(size_) / static_cast<double>(mlf_))) +
- 1));
-
- if (min_buckets != bucket_count_)
- this->rehash_impl(min_buckets);
- }
-}
-
-template <typename Types>
-inline void table<Types>::reserve(std::size_t num_elements)
-{
- rehash(static_cast<std::size_t>(
- std::ceil(static_cast<double>(num_elements) / mlf_)));
-}
-
-template <typename Types>
-inline void table<Types>::rehash_impl(std::size_t num_buckets)
-{
- BOOST_ASSERT(this->buckets_);
-
- this->create_buckets(num_buckets);
- link_pointer prev = this->get_previous_start();
- while (prev->next_) {
- node_pointer group_last = node_algo::last_for_rehash(prev);
- bucket_pointer b =
- this->get_bucket(this->hash_to_bucket(group_last->hash_));
- if (!b->next_) {
- b->next_ = prev;
- prev = group_last;
- } else {
- link_pointer next = group_last->next_;
- group_last->next_ = b->next_->next_;
- b->next_->next_ = prev->next_;
- prev->next_ = next;
- }
- }
-}
-
-#if defined(BOOST_MSVC)
-#pragma warning(pop)
-#endif
-
-////////////////////////////////////////////////////////////////////////
-// key extractors
-//
-// no throw
-//
-// 'extract_key' is called with the emplace parameters to return a
-// key if available or 'no_key' is one isn't and will need to be
-// constructed. This could be done by overloading the emplace implementation
-// for the different cases, but that's a bit tricky on compilers without
-// variadic templates.
-
-struct no_key
-{
- no_key() {}
- template <class T> no_key(T const&) {}
-};
-
-template <typename Key, typename T> struct is_key
-{
- template <typename T2> static choice1::type test(T2 const&);
- static choice2::type test(Key const&);
-
- enum
- {
- value = sizeof(test(boost::unordered::detail::make<T>())) ==
- sizeof(choice2::type)
- };
-
- typedef typename boost::detail::if_true<value>::BOOST_NESTED_TEMPLATE
- then<Key const&, no_key>::type type;
-};
-
-template <class ValueType> struct set_extractor
-{
- typedef ValueType value_type;
- typedef ValueType key_type;
-
- static key_type const& extract(value_type const& v) { return v; }
-
- static no_key extract() { return no_key(); }
-
- template <class Arg> static no_key extract(Arg const&) { return no_key(); }
-
-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- template <class Arg1, class Arg2, class... Args>
- static no_key extract(Arg1 const&, Arg2 const&, Args const&...)
- {
- return no_key();
- }
-#else
- template <class Arg1, class Arg2>
- static no_key extract(Arg1 const&, Arg2 const&)
- {
- return no_key();
- }
-#endif
-};
-
-template <class ValueType> struct map_extractor
-{
- typedef ValueType value_type;
- typedef typename boost::remove_const<typename boost::unordered::detail::
- pair_traits<ValueType>::first_type>::type key_type;
-
- static key_type const& extract(value_type const& v) { return v.first; }
-
- template <class Second>
- static key_type const& extract(std::pair<key_type, Second> const& v)
- {
- return v.first;
- }
-
- template <class Second>
- static key_type const& extract(std::pair<key_type const, Second> const& v)
- {
- return v.first;
- }
-
- template <class Arg1>
- static key_type const& extract(key_type const& k, Arg1 const&)
- {
- return k;
- }
-
- static no_key extract() { return no_key(); }
-
- template <class Arg> static no_key extract(Arg const&) { return no_key(); }
-
- template <class Arg1, class Arg2>
- static no_key extract(Arg1 const&, Arg2 const&)
- {
- return no_key();
- }
-
-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- template <class Arg1, class Arg2, class Arg3, class... Args>
- static no_key extract(Arg1 const&, Arg2 const&, Arg3 const&, Args const&...)
- {
- return no_key();
- }
-#endif
-
-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
-
-#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
- template <typename T2> \
- static no_key extract(boost::unordered::piecewise_construct_t, \
- namespace_ tuple<> const&, T2 const&) \
- { \
- return no_key(); \
- } \
- \
- template <typename T, typename T2> \
- static typename is_key<key_type, T>::type extract( \
- boost::unordered::piecewise_construct_t, namespace_ tuple<T> const& k, \
- T2 const&) \
- { \
- return typename is_key<key_type, T>::type(namespace_ get<0>(k)); \
- }
-
-#else
-
-#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
- static no_key extract( \
- boost::unordered::piecewise_construct_t, namespace_ tuple<> const&) \
- { \
- return no_key(); \
- } \
- \
- template <typename T> \
- static typename is_key<key_type, T>::type extract( \
- boost::unordered::piecewise_construct_t, namespace_ tuple<T> const& k) \
- { \
- return typename is_key<key_type, T>::type(namespace_ get<0>(k)); \
- }
-
-#endif
-
- BOOST_UNORDERED_KEY_FROM_TUPLE(boost::)
-
-#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
- BOOST_UNORDERED_KEY_FROM_TUPLE(std::)
-#endif
-};
-
-////////////////////////////////////////////////////////////////////////
-// Unique nodes
-
-template <typename A, typename T>
-struct unique_node : boost::unordered::detail::value_base<T>
-{
- typedef typename ::boost::unordered::detail::rebind_wrap<A,
- unique_node<A, T> >::type allocator;
- typedef typename ::boost::unordered::detail::allocator_traits<
- allocator>::pointer node_pointer;
- typedef node_pointer link_pointer;
- typedef typename ::boost::unordered::detail::rebind_wrap<A,
- bucket<node_pointer> >::type bucket_allocator;
- typedef typename ::boost::unordered::detail::allocator_traits<
- bucket_allocator>::pointer bucket_pointer;
-
- link_pointer next_;
- std::size_t hash_;
-
- unique_node() : next_(), hash_(0) {}
-
- void init(node_pointer) {}
-
- private:
- unique_node& operator=(unique_node const&);
-};
-
-template <typename T> struct ptr_node : boost::unordered::detail::ptr_bucket
-{
- typedef T value_type;
- typedef boost::unordered::detail::ptr_bucket bucket_base;
- typedef ptr_node<T>* node_pointer;
- typedef ptr_bucket* link_pointer;
- typedef ptr_bucket* bucket_pointer;
-
- std::size_t hash_;
- boost::unordered::detail::value_base<T> value_base_;
-
- ptr_node() : bucket_base(), hash_(0) {}
-
- void init(node_pointer) {}
-
- void* address() { return value_base_.address(); }
- value_type& value() { return value_base_.value(); }
- value_type* value_ptr() { return value_base_.value_ptr(); }
-
- private:
- ptr_node& operator=(ptr_node const&);
-};
-
-template <typename N> struct node_algo
-{
- typedef typename N::node_pointer node_pointer;
- typedef typename N::link_pointer link_pointer;
- typedef typename N::bucket_pointer bucket_pointer;
-
- static node_pointer next_node(link_pointer n)
- {
- return static_cast<node_pointer>(n->next_);
- }
-
- static node_pointer next_for_find(node_pointer n)
- {
- return static_cast<node_pointer>(n->next_);
- }
-
- static link_pointer next_for_erase(link_pointer prev)
- {
- return prev->next_;
- }
-
- // Group together all nodes with equal hash value, this may
- // include nodes with different keys, but that's okay because
- // they will end up in the same bucket.
- static node_pointer last_for_rehash(link_pointer prev)
- {
- node_pointer n = next_node(prev);
- std::size_t hash = n->hash_;
- for (;;) {
- node_pointer next = next_node(n);
- if (!next || next->hash_ != hash) {
- return n;
- }
- n = next;
- }
- }
-
- template <typename Table>
- static node_pointer next_group(node_pointer n, Table const* t)
- {
- node_pointer n1 = n;
- do {
- n1 = next_node(n1);
- } while (
- n1 && t->key_eq()(t->get_key(n->value()), t->get_key(n1->value())));
- return n1;
- }
-
- template <typename Table>
- static std::size_t count(node_pointer n, Table const* t)
- {
- std::size_t x = 0;
- node_pointer it = n;
- do {
- ++x;
- it = next_node(it);
- } while (
- it && t->key_eq()(t->get_key(n->value()), t->get_key(it->value())));
-
- return x;
- }
-
- // Add node 'n' after 'pos'.
- // This results in a different order to the grouped implementation.
- static inline void add_to_node_group(node_pointer n, node_pointer pos)
- {
- n->next_ = pos->next_;
- pos->next_ = n;
- }
-
- static inline node_pointer extract_first_node(link_pointer prev)
- {
- node_pointer n = next_node(prev);
- prev->next_ = n->next_;
- return n;
- }
-
- static link_pointer split_groups(node_pointer, node_pointer)
- {
- return link_pointer();
- }
-};
-
-// If the allocator uses raw pointers use ptr_node
-// Otherwise use node.
-
-template <typename A, typename T, typename NodePtr, typename BucketPtr>
-struct pick_node2
-{
- typedef boost::unordered::detail::unique_node<A, T> node;
-
- typedef typename boost::unordered::detail::allocator_traits<
- typename boost::unordered::detail::rebind_wrap<A, node>::type>::pointer
- node_pointer;
-
- typedef boost::unordered::detail::bucket<node_pointer> bucket;
- typedef node_pointer link_pointer;
-};
-
-template <typename A, typename T>
-struct pick_node2<A, T, boost::unordered::detail::ptr_node<T>*,
- boost::unordered::detail::ptr_bucket*>
-{
- typedef boost::unordered::detail::ptr_node<T> node;
- typedef boost::unordered::detail::ptr_bucket bucket;
- typedef bucket* link_pointer;
-};
-
-template <typename A, typename T> struct pick_node
-{
- typedef typename boost::remove_const<T>::type nonconst;
-
- typedef boost::unordered::detail::allocator_traits<
- typename boost::unordered::detail::rebind_wrap<A,
- boost::unordered::detail::ptr_node<nonconst> >::type>
- tentative_node_traits;
-
- typedef boost::unordered::detail::allocator_traits<
- typename boost::unordered::detail::rebind_wrap<A,
- boost::unordered::detail::ptr_bucket>::type>
- tentative_bucket_traits;
-
- typedef pick_node2<A, nonconst, typename tentative_node_traits::pointer,
- typename tentative_bucket_traits::pointer>
- pick;
-
- typedef typename pick::node node;
- typedef typename pick::bucket bucket;
- typedef typename pick::link_pointer link_pointer;
- typedef boost::unordered::detail::node_algo<node> node_algo;
-};
-
-template <typename Types>
-struct table_impl : boost::unordered::detail::table<Types>
-{
- typedef boost::unordered::detail::table<Types> table;
- typedef typename table::value_type value_type;
- typedef typename table::node node;
- typedef typename table::bucket bucket;
- typedef typename table::policy policy;
- typedef typename table::node_pointer node_pointer;
- typedef typename table::node_allocator node_allocator;
- typedef typename table::node_allocator_traits node_allocator_traits;
- typedef typename table::bucket_pointer bucket_pointer;
- typedef typename table::link_pointer link_pointer;
- typedef typename table::hasher hasher;
- typedef typename table::key_equal key_equal;
- typedef typename table::const_key_type const_key_type;
- typedef typename table::node_constructor node_constructor;
- typedef typename table::node_tmp node_tmp;
- typedef typename table::extractor extractor;
- typedef typename table::iterator iterator;
- typedef typename table::c_iterator c_iterator;
- typedef typename table::node_algo node_algo;
-
- typedef std::pair<iterator, bool> emplace_return;
-
- // Constructors
-
- table_impl(std::size_t n, hasher const& hf, key_equal const& eq,
- node_allocator const& a)
- : table(n, hf, eq, a)
- {
- }
-
- table_impl(table_impl const& x)
- : table(x, node_allocator_traits::select_on_container_copy_construction(
- x.node_alloc()))
- {
- this->init(x);
- }
-
- table_impl(table_impl const& x, node_allocator const& a) : table(x, a)
- {
- this->init(x);
- }
-
- table_impl(table_impl& x, boost::unordered::detail::move_tag m)
- : table(x, m)
- {
- }
-
- table_impl(table_impl& x, node_allocator const& a,
- boost::unordered::detail::move_tag m)
- : table(x, a, m)
- {
- this->move_init(x);
- }
-
- // Accessors
- std::size_t count(const_key_type& k) const
- {
- return this->find_node(k) ? 1 : 0;
- }
-
- value_type& at(const_key_type& k) const
- {
- if (this->size_) {
- node_pointer n = this->find_node(k);
- if (n)
- return n->value();
- }
-
- boost::throw_exception(
- std::out_of_range("Unable to find key in unordered_map."));
- }
-
- std::pair<iterator, iterator> equal_range(const_key_type& k) const
- {
- node_pointer n = this->find_node(k);
- return std::make_pair(
- iterator(n), iterator(n ? node_algo::next_node(n) : n));
- }
+ ////////////////////////////////////////////////////////////////////////
+ // Unique keys
// equals
- bool equals(table_impl const& other) const
+ bool equals_unique(table const& other) const
{
if (this->size_ != other.size_)
return false;
- for (node_pointer n1 = this->begin(); n1;
- n1 = node_algo::next_node(n1)) {
- node_pointer n2 = other.find_node(other.get_key(n1->value()));
+ for (node_pointer n1 = this->begin(); n1; n1 = next_node(n1)) {
+ node_pointer n2 = other.find_node(other.get_key(n1));
if (!n2 || n1->value() != n2->value())
return false;
@@ -3709,19 +3361,20 @@ struct table_impl : boost::unordered::detail::table<Types>
// Emplace/Insert
- inline node_pointer add_node(node_pointer n, std::size_t key_hash)
+ inline node_pointer add_node_unique(node_pointer n, std::size_t key_hash)
{
- n->hash_ = key_hash;
+ std::size_t bucket_index = this->hash_to_bucket(key_hash);
+ bucket_pointer b = this->get_bucket(bucket_index);
- bucket_pointer b = this->get_bucket(this->hash_to_bucket(key_hash));
+ // TODO: Do this need to set_first_in_group ?
+ n->bucket_info_ = bucket_index;
+ // n->set_first_in_group();
if (!b->next_) {
link_pointer start_node = this->get_previous_start();
if (start_node->next_) {
- this->get_bucket(this->hash_to_bucket(
- node_algo::next_node(start_node)->hash_))
- ->next_ = n;
+ this->get_bucket(node_bucket(next_node(start_node)))->next_ = n;
}
b->next_ = start_node;
@@ -3736,102 +3389,28 @@ struct table_impl : boost::unordered::detail::table<Types>
return n;
}
- inline node_pointer resize_and_add_node(
+ inline node_pointer resize_and_add_node_unique(
node_pointer n, std::size_t key_hash)
{
node_tmp b(n, this->node_alloc());
this->reserve_for_insert(this->size_ + 1);
- return this->add_node(b.release(), key_hash);
- }
-
-#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
-#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- emplace_return emplace(boost::unordered::detail::emplace_args1<
- boost::unordered::detail::please_ignore_this_overload> const&)
- {
- BOOST_ASSERT(false);
- return emplace_return(iterator(), false);
- }
-
- iterator emplace_hint(
- c_iterator,
- boost::unordered::detail::emplace_args1<
- boost::unordered::detail::please_ignore_this_overload> const&)
- {
- BOOST_ASSERT(false);
- return iterator();
- }
-#else
- emplace_return emplace(
- boost::unordered::detail::please_ignore_this_overload const&)
- {
- BOOST_ASSERT(false);
- return emplace_return(iterator(), false);
- }
-
- iterator emplace_hint(c_iterator,
- boost::unordered::detail::please_ignore_this_overload const&)
- {
- BOOST_ASSERT(false);
- return iterator();
- }
-#endif
-#endif
-
- template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
- emplace_return emplace(BOOST_UNORDERED_EMPLACE_ARGS)
- {
-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- return emplace_impl(extractor::extract(BOOST_UNORDERED_EMPLACE_FORWARD),
- BOOST_UNORDERED_EMPLACE_FORWARD);
-#else
- return emplace_impl(extractor::extract(args.a0, args.a1),
- BOOST_UNORDERED_EMPLACE_FORWARD);
-#endif
+ return this->add_node_unique(b.release(), key_hash);
}
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
- iterator emplace_hint(c_iterator hint, BOOST_UNORDERED_EMPLACE_ARGS)
- {
-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- return emplace_hint_impl(hint,
- extractor::extract(BOOST_UNORDERED_EMPLACE_FORWARD),
- BOOST_UNORDERED_EMPLACE_FORWARD);
-#else
- return emplace_hint_impl(hint, extractor::extract(args.a0, args.a1),
- BOOST_UNORDERED_EMPLACE_FORWARD);
-#endif
- }
-
-#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- template <typename A0>
- emplace_return emplace(
- boost::unordered::detail::emplace_args1<A0> const& args)
- {
- return emplace_impl(extractor::extract(args.a0), args);
- }
-
- template <typename A0>
- iterator emplace_hint(c_iterator hint,
- boost::unordered::detail::emplace_args1<A0> const& args)
- {
- return emplace_hint_impl(hint, extractor::extract(args.a0), args);
- }
-#endif
-
- template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
- iterator emplace_hint_impl(
+ iterator emplace_hint_unique(
c_iterator hint, const_key_type& k, BOOST_UNORDERED_EMPLACE_ARGS)
{
- if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
+ if (hint.node_ && this->key_eq()(k, this->get_key(hint.node_))) {
return iterator(hint.node_);
} else {
- return emplace_impl(k, BOOST_UNORDERED_EMPLACE_FORWARD).first;
+ return emplace_unique(k, BOOST_UNORDERED_EMPLACE_FORWARD).first;
}
}
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
- emplace_return emplace_impl(const_key_type& k, BOOST_UNORDERED_EMPLACE_ARGS)
+ emplace_return emplace_unique(
+ const_key_type& k, BOOST_UNORDERED_EMPLACE_ARGS)
{
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
@@ -3839,7 +3418,7 @@ struct table_impl : boost::unordered::detail::table<Types>
return emplace_return(iterator(pos), false);
} else {
return emplace_return(
- iterator(this->resize_and_add_node(
+ iterator(this->resize_and_add_node_unique(
boost::unordered::detail::func::construct_node_from_args(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
key_hash)),
@@ -3848,14 +3427,14 @@ struct table_impl : boost::unordered::detail::table<Types>
}
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
- iterator emplace_hint_impl(
+ iterator emplace_hint_unique(
c_iterator hint, no_key, BOOST_UNORDERED_EMPLACE_ARGS)
{
node_tmp b(boost::unordered::detail::func::construct_node_from_args(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
this->node_alloc());
- const_key_type& k = this->get_key(b.node_->value());
- if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
+ const_key_type& k = this->get_key(b.node_);
+ if (hint.node_ && this->key_eq()(k, this->get_key(hint.node_))) {
return iterator(hint.node_);
}
std::size_t key_hash = this->hash(k);
@@ -3863,30 +3442,31 @@ struct table_impl : boost::unordered::detail::table<Types>
if (pos) {
return iterator(pos);
} else {
- return iterator(this->resize_and_add_node(b.release(), key_hash));
+ return iterator(
+ this->resize_and_add_node_unique(b.release(), key_hash));
}
}
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
- emplace_return emplace_impl(no_key, BOOST_UNORDERED_EMPLACE_ARGS)
+ emplace_return emplace_unique(no_key, BOOST_UNORDERED_EMPLACE_ARGS)
{
node_tmp b(boost::unordered::detail::func::construct_node_from_args(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
this->node_alloc());
- const_key_type& k = this->get_key(b.node_->value());
+ const_key_type& k = this->get_key(b.node_);
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
if (pos) {
return emplace_return(iterator(pos), false);
} else {
- return emplace_return(
- iterator(this->resize_and_add_node(b.release(), key_hash)),
+ return emplace_return(iterator(this->resize_and_add_node_unique(
+ b.release(), key_hash)),
true);
}
}
template <typename Key>
- emplace_return try_emplace_impl(BOOST_FWD_REF(Key) k)
+ emplace_return try_emplace_unique(BOOST_FWD_REF(Key) k)
{
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
@@ -3894,7 +3474,7 @@ struct table_impl : boost::unordered::detail::table<Types>
return emplace_return(iterator(pos), false);
} else {
return emplace_return(
- iterator(this->resize_and_add_node(
+ iterator(this->resize_and_add_node_unique(
boost::unordered::detail::func::construct_node_pair(
this->node_alloc(), boost::forward<Key>(k)),
key_hash)),
@@ -3903,17 +3483,17 @@ struct table_impl : boost::unordered::detail::table<Types>
}
template <typename Key>
- iterator try_emplace_hint_impl(c_iterator hint, BOOST_FWD_REF(Key) k)
+ iterator try_emplace_hint_unique(c_iterator hint, BOOST_FWD_REF(Key) k)
{
if (hint.node_ && this->key_eq()(hint->first, k)) {
return iterator(hint.node_);
} else {
- return try_emplace_impl(k).first;
+ return try_emplace_unique(k).first;
}
}
template <typename Key, BOOST_UNORDERED_EMPLACE_TEMPLATE>
- emplace_return try_emplace_impl(
+ emplace_return try_emplace_unique(
BOOST_FWD_REF(Key) k, BOOST_UNORDERED_EMPLACE_ARGS)
{
std::size_t key_hash = this->hash(k);
@@ -3922,7 +3502,7 @@ struct table_impl : boost::unordered::detail::table<Types>
return emplace_return(iterator(pos), false);
} else {
return emplace_return(
- iterator(this->resize_and_add_node(
+ iterator(this->resize_and_add_node_unique(
boost::unordered::detail::func::
construct_node_pair_from_args(this->node_alloc(),
boost::forward<Key>(k),
@@ -3933,18 +3513,18 @@ struct table_impl : boost::unordered::detail::table<Types>
}
template <typename Key, BOOST_UNORDERED_EMPLACE_TEMPLATE>
- iterator try_emplace_hint_impl(
+ iterator try_emplace_hint_unique(
c_iterator hint, BOOST_FWD_REF(Key) k, BOOST_UNORDERED_EMPLACE_ARGS)
{
if (hint.node_ && this->key_eq()(hint->first, k)) {
return iterator(hint.node_);
} else {
- return try_emplace_impl(k, BOOST_UNORDERED_EMPLACE_FORWARD).first;
+ return try_emplace_unique(k, BOOST_UNORDERED_EMPLACE_FORWARD).first;
}
}
template <typename Key, typename M>
- emplace_return insert_or_assign_impl(
+ emplace_return insert_or_assign_unique(
BOOST_FWD_REF(Key) k, BOOST_FWD_REF(M) obj)
{
std::size_t key_hash = this->hash(k);
@@ -3955,7 +3535,7 @@ struct table_impl : boost::unordered::detail::table<Types>
return emplace_return(iterator(pos), false);
} else {
return emplace_return(
- iterator(this->resize_and_add_node(
+ iterator(this->resize_and_add_node_unique(
boost::unordered::detail::func::construct_node_pair(
this->node_alloc(), boost::forward<Key>(k),
boost::forward<M>(obj)),
@@ -3965,10 +3545,10 @@ struct table_impl : boost::unordered::detail::table<Types>
}
template <typename NodeType, typename InsertReturnType>
- void move_insert_node_type(NodeType& np, InsertReturnType& result)
+ void move_insert_node_type_unique(NodeType& np, InsertReturnType& result)
{
if (np) {
- const_key_type& k = this->get_key(np.ptr_->value());
+ const_key_type& k = this->get_key(np.ptr_);
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
@@ -3977,7 +3557,8 @@ struct table_impl : boost::unordered::detail::table<Types>
result.position = iterator(pos);
} else {
this->reserve_for_insert(this->size_ + 1);
- result.position = iterator(this->add_node(np.ptr_, key_hash));
+ result.position =
+ iterator(this->add_node_unique(np.ptr_, key_hash));
result.inserted = true;
np.ptr_ = node_pointer();
}
@@ -3985,27 +3566,28 @@ struct table_impl : boost::unordered::detail::table<Types>
}
template <typename NodeType>
- iterator move_insert_node_type_with_hint(c_iterator hint, NodeType& np)
+ iterator move_insert_node_type_with_hint_unique(
+ c_iterator hint, NodeType& np)
{
if (!np) {
return iterator();
}
- const_key_type& k = this->get_key(np.ptr_->value());
- if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
+ const_key_type& k = this->get_key(np.ptr_);
+ if (hint.node_ && this->key_eq()(k, this->get_key(hint.node_))) {
return iterator(hint.node_);
}
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
if (!pos) {
this->reserve_for_insert(this->size_ + 1);
- pos = this->add_node(np.ptr_, key_hash);
+ pos = this->add_node_unique(np.ptr_, key_hash);
np.ptr_ = node_pointer();
}
return iterator(pos);
}
template <typename Types2>
- void merge_impl(boost::unordered::detail::table<Types2>& other)
+ void merge_unique(boost::unordered::detail::table<Types2>& other)
{
typedef boost::unordered::detail::table<Types2> other_table;
BOOST_STATIC_ASSERT(
@@ -4016,8 +3598,8 @@ struct table_impl : boost::unordered::detail::table<Types>
link_pointer prev = other.get_previous_start();
while (prev->next_) {
- node_pointer n = other_table::node_algo::next_node(prev);
- const_key_type& k = this->get_key(n->value());
+ node_pointer n = other_table::next_node(prev);
+ const_key_type& k = this->get_key(n);
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
@@ -4025,12 +3607,14 @@ struct table_impl : boost::unordered::detail::table<Types>
prev = n;
} else {
this->reserve_for_insert(this->size_ + 1);
- other_table::node_algo::split_groups(
- n, other_table::node_algo::next_node(n));
- prev->next_ = n->next_;
+ node_pointer n2 = next_node(n);
+ prev->next_ = n2;
+ if (n2 && n->is_first_in_group()) {
+ n2->set_first_in_group();
+ }
--other.size_;
- other.fix_bucket(other.hash_to_bucket(n->hash_), prev);
- this->add_node(n, key_hash);
+ other.fix_bucket(other.node_bucket(n), prev, n2);
+ this->add_node_unique(n, key_hash);
}
}
}
@@ -4042,32 +3626,21 @@ struct table_impl : boost::unordered::detail::table<Types>
// if hash function throws, or inserting > 1 element, basic exception
// safety strong otherwise
- template <class InputIt> void insert_range(InputIt i, InputIt j)
- {
- if (i != j)
- return insert_range_impl(extractor::extract(*i), i, j);
- }
-
template <class InputIt>
- void insert_range_impl(const_key_type& k, InputIt i, InputIt j)
+ void insert_range_unique(const_key_type& k, InputIt i, InputIt j)
{
- insert_range_impl2(k, i, j);
+ insert_range_unique2(k, i, j);
while (++i != j) {
// Note: can't use get_key as '*i' might not be value_type - it
// could be a pair with first_types as key_type without const or
// a different second_type.
- //
- // TODO: Might be worth storing the value_type instead of the
- // key here. Could be more efficient if '*i' is expensive. Could
- // be less efficient if copying the full value_type is
- // expensive.
- insert_range_impl2(extractor::extract(*i), i, j);
+ insert_range_unique2(extractor::extract(*i), i, j);
}
}
template <class InputIt>
- void insert_range_impl2(const_key_type& k, InputIt i, InputIt j)
+ void insert_range_unique2(const_key_type& k, InputIt i, InputIt j)
{
// No side effects in this initial code
std::size_t key_hash = this->hash(k);
@@ -4080,12 +3653,12 @@ struct table_impl : boost::unordered::detail::table<Types>
if (this->size_ + 1 > this->max_load_)
this->reserve_for_insert(
this->size_ + boost::unordered::detail::insert_size(i, j));
- this->add_node(b.release(), key_hash);
+ this->add_node_unique(b.release(), key_hash);
}
}
template <class InputIt>
- void insert_range_impl(no_key, InputIt i, InputIt j)
+ void insert_range_unique(no_key, InputIt i, InputIt j)
{
node_constructor a(this->node_alloc());
@@ -4093,11 +3666,11 @@ struct table_impl : boost::unordered::detail::table<Types>
if (!a.node_) {
a.create_node();
}
- boost::unordered::detail::func::call_construct(
- a.alloc_, a.node_->value_ptr(), *i);
+ BOOST_UNORDERED_CALL_CONSTRUCT1(
+ node_allocator_traits, a.alloc_, a.node_->value_ptr(), *i);
node_tmp b(a.release(), a.alloc_);
- const_key_type& k = this->get_key(b.node_->value());
+ const_key_type& k = this->get_key(b.node_);
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
@@ -4107,7 +3680,7 @@ struct table_impl : boost::unordered::detail::table<Types>
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
this->reserve_for_insert(this->size_ + 1);
- this->add_node(b.release(), key_hash);
+ this->add_node_unique(b.release(), key_hash);
}
} while (++i != j);
}
@@ -4115,19 +3688,19 @@ struct table_impl : boost::unordered::detail::table<Types>
////////////////////////////////////////////////////////////////////////
// Extract
- inline node_pointer extract_by_iterator(c_iterator i)
+ inline node_pointer extract_by_iterator_unique(c_iterator i)
{
node_pointer n = i.node_;
BOOST_ASSERT(n);
- std::size_t key_hash = n->hash_;
- std::size_t bucket_index = this->hash_to_bucket(key_hash);
+ std::size_t bucket_index = this->node_bucket(n);
link_pointer prev = this->get_previous_start(bucket_index);
while (prev->next_ != n) {
prev = prev->next_;
}
- prev->next_ = n->next_;
+ node_pointer n2 = next_node(n);
+ prev->next_ = n2;
--this->size_;
- this->fix_bucket(bucket_index, prev);
+ this->fix_bucket(bucket_index, prev, n2);
n->next_ = link_pointer();
return n;
}
@@ -4137,40 +3710,27 @@ struct table_impl : boost::unordered::detail::table<Types>
//
// no throw
- std::size_t erase_key(const_key_type& k)
+ std::size_t erase_key_unique(const_key_type& k)
{
if (!this->size_)
return 0;
std::size_t key_hash = this->hash(k);
std::size_t bucket_index = this->hash_to_bucket(key_hash);
- link_pointer prev = this->find_previous_node(k, key_hash, bucket_index);
+ link_pointer prev = this->find_previous_node(k, bucket_index);
if (!prev)
return 0;
- link_pointer end = node_algo::next_node(prev)->next_;
- this->delete_nodes(prev, end);
- this->fix_bucket(bucket_index, prev);
+ node_pointer n = next_node(prev);
+ node_pointer n2 = next_node(n);
+ prev->next_ = n2;
+ --size_;
+ this->fix_bucket(bucket_index, prev, n2);
+ this->destroy_node(n);
return 1;
}
- iterator erase(c_iterator r)
+ void erase_nodes_unique(node_pointer i, node_pointer j)
{
- BOOST_ASSERT(r.node_);
- node_pointer next = node_algo::next_node(r.node_);
- erase_nodes(r.node_, next);
- return iterator(next);
- }
-
- iterator erase_range(c_iterator r1, c_iterator r2)
- {
- if (r1 == r2)
- return iterator(r2.node_);
- erase_nodes(r1.node_, r2.node_);
- return iterator(r2.node_);
- }
-
- void erase_nodes(node_pointer i, node_pointer j)
- {
- std::size_t bucket_index = this->hash_to_bucket(i->hash_);
+ std::size_t bucket_index = this->node_bucket(i);
// Find the node before i.
link_pointer prev = this->get_previous_start(bucket_index);
@@ -4178,343 +3738,81 @@ struct table_impl : boost::unordered::detail::table<Types>
prev = prev->next_;
// Delete the nodes.
+ prev->next_ = j;
do {
- this->delete_node(prev);
- bucket_index = this->fix_bucket(bucket_index, prev);
- } while (prev->next_ != j);
+ node_pointer next = next_node(i);
+ destroy_node(i);
+ --size_;
+ bucket_index = this->fix_bucket(bucket_index, prev, next);
+ i = next;
+ } while (i != j);
}
////////////////////////////////////////////////////////////////////////
- // fill_buckets
+ // fill_buckets_unique
- void copy_buckets(table const& src)
+ void copy_buckets(table const& src, true_type)
{
this->create_buckets(this->bucket_count_);
- for (node_pointer n = src.begin(); n; n = node_algo::next_node(n)) {
- this->add_node(boost::unordered::detail::func::construct_node(
- this->node_alloc(), n->value()),
- n->hash_);
+ for (node_pointer n = src.begin(); n; n = next_node(n)) {
+ std::size_t key_hash = this->hash(this->get_key(n));
+ this->add_node_unique(
+ boost::unordered::detail::func::construct_node(
+ this->node_alloc(), n->value()),
+ key_hash);
}
}
+ // TODO: Should be move_buckets_uniq
void move_buckets(table const& src)
{
this->create_buckets(this->bucket_count_);
- for (node_pointer n = src.begin(); n; n = node_algo::next_node(n)) {
- this->add_node(boost::unordered::detail::func::construct_node(
- this->node_alloc(), boost::move(n->value())),
- n->hash_);
+ for (node_pointer n = src.begin(); n; n = next_node(n)) {
+ std::size_t key_hash = this->hash(this->get_key(n));
+ this->add_node_unique(
+ boost::unordered::detail::func::construct_node(
+ this->node_alloc(), boost::move(n->value())),
+ key_hash);
}
}
- void assign_buckets(table const& src)
+ void assign_buckets(table const& src, true_type)
{
node_holder<node_allocator> holder(*this);
- for (node_pointer n = src.begin(); n; n = node_algo::next_node(n)) {
- this->add_node(holder.copy_of(n->value()), n->hash_);
+ for (node_pointer n = src.begin(); n; n = next_node(n)) {
+ std::size_t key_hash = this->hash(this->get_key(n));
+ this->add_node_unique(holder.copy_of(n->value()), key_hash);
}
}
- void move_assign_buckets(table& src)
+ void move_assign_buckets(table& src, true_type)
{
node_holder<node_allocator> holder(*this);
- for (node_pointer n = src.begin(); n; n = node_algo::next_node(n)) {
- this->add_node(holder.move_copy_of(n->value()), n->hash_);
- }
- }
-};
-
-////////////////////////////////////////////////////////////////////////
-// Grouped nodes
-
-template <typename A, typename T>
-struct grouped_node : boost::unordered::detail::value_base<T>
-{
- typedef typename ::boost::unordered::detail::rebind_wrap<A,
- grouped_node<A, T> >::type allocator;
- typedef typename ::boost::unordered::detail::allocator_traits<
- allocator>::pointer node_pointer;
- typedef node_pointer link_pointer;
- typedef typename ::boost::unordered::detail::rebind_wrap<A,
- bucket<node_pointer> >::type bucket_allocator;
- typedef typename ::boost::unordered::detail::allocator_traits<
- bucket_allocator>::pointer bucket_pointer;
-
- link_pointer next_;
- node_pointer group_prev_;
- std::size_t hash_;
-
- grouped_node() : next_(), group_prev_(), hash_(0) {}
-
- void init(node_pointer self) { group_prev_ = self; }
-
- private:
- grouped_node& operator=(grouped_node const&);
-};
-
-template <typename T>
-struct grouped_ptr_node : boost::unordered::detail::ptr_bucket
-{
- typedef T value_type;
- typedef boost::unordered::detail::ptr_bucket bucket_base;
- typedef grouped_ptr_node<T>* node_pointer;
- typedef ptr_bucket* link_pointer;
- typedef ptr_bucket* bucket_pointer;
-
- node_pointer group_prev_;
- std::size_t hash_;
- boost::unordered::detail::value_base<T> value_base_;
-
- grouped_ptr_node() : bucket_base(), group_prev_(0), hash_(0) {}
-
- void init(node_pointer self) { group_prev_ = self; }
-
- void* address() { return value_base_.address(); }
- value_type& value() { return value_base_.value(); }
- value_type* value_ptr() { return value_base_.value_ptr(); }
-
- private:
- grouped_ptr_node& operator=(grouped_ptr_node const&);
-};
-
-template <typename N> struct grouped_node_algo
-{
- typedef typename N::node_pointer node_pointer;
- typedef typename N::link_pointer link_pointer;
- typedef typename N::bucket_pointer bucket_pointer;
-
- static node_pointer next_node(link_pointer n)
- {
- return static_cast<node_pointer>(n->next_);
- }
-
- static node_pointer next_for_find(node_pointer n)
- {
- return static_cast<node_pointer>(n->group_prev_->next_);
- }
-
- static link_pointer next_for_erase(link_pointer prev)
- {
- return static_cast<node_pointer>(prev->next_)->group_prev_;
- }
-
- static node_pointer last_for_rehash(link_pointer prev)
- {
- return static_cast<node_pointer>(prev->next_)->group_prev_;
- }
-
- // The 'void*' arguments are pointers to the table, which we
- // will ignore, but without groups they could be used to
- // access the various functions for dealing with values and keys.
- static node_pointer next_group(node_pointer n, void const*)
- {
- return static_cast<node_pointer>(n->group_prev_->next_);
- }
-
- static std::size_t count(node_pointer n, void const*)
- {
- std::size_t x = 0;
- node_pointer it = n;
- do {
- it = it->group_prev_;
- ++x;
- } while (it != n);
-
- return x;
- }
-
- // Adds node 'n' to the group containing 'pos'.
- // If 'pos' is the first node in group, add to the end of the group,
- // otherwise add before 'pos'. Other versions will probably behave
- // differently.
- static inline void add_to_node_group(node_pointer n, node_pointer pos)
- {
- n->next_ = pos->group_prev_->next_;
- n->group_prev_ = pos->group_prev_;
- pos->group_prev_->next_ = n;
- pos->group_prev_ = n;
- }
-
- static inline node_pointer extract_first_node(link_pointer prev)
- {
- node_pointer n = next_node(prev);
- if (n->group_prev_ != n) {
- node_pointer next = next_node(n);
- next->group_prev_ = n->group_prev_;
- n->group_prev_ = n;
+ for (node_pointer n = src.begin(); n; n = next_node(n)) {
+ std::size_t key_hash = this->hash(this->get_key(n));
+ this->add_node_unique(holder.move_copy_of(n->value()), key_hash);
}
- prev->next_ = n->next_;
- return n;
- }
-
- // Split the groups containing 'i' and 'j' so that they can
- // be safely erased/extracted.
- static link_pointer split_groups(node_pointer i, node_pointer j)
- {
- node_pointer prev = i->group_prev_;
- if (prev->next_ != i)
- prev = node_pointer();
-
- if (j) {
- node_pointer first = j;
- while (first != i && first->group_prev_->next_ == first) {
- first = first->group_prev_;
- }
-
- boost::swap(first->group_prev_, j->group_prev_);
- if (first == i)
- return prev;
- }
-
- if (prev) {
- node_pointer first = prev;
- while (first->group_prev_->next_ == first) {
- first = first->group_prev_;
- }
- boost::swap(first->group_prev_, i->group_prev_);
- }
-
- return prev;
- }
-};
-
-// If the allocator uses raw pointers use grouped_ptr_node
-// Otherwise use grouped_node.
-
-template <typename A, typename T, typename NodePtr, typename BucketPtr>
-struct pick_grouped_node2
-{
- typedef boost::unordered::detail::grouped_node<A, T> node;
-
- typedef typename boost::unordered::detail::allocator_traits<
- typename boost::unordered::detail::rebind_wrap<A, node>::type>::pointer
- node_pointer;
-
- typedef boost::unordered::detail::bucket<node_pointer> bucket;
- typedef node_pointer link_pointer;
-};
-
-template <typename A, typename T>
-struct pick_grouped_node2<A, T, boost::unordered::detail::grouped_ptr_node<T>*,
- boost::unordered::detail::ptr_bucket*>
-{
- typedef boost::unordered::detail::grouped_ptr_node<T> node;
- typedef boost::unordered::detail::ptr_bucket bucket;
- typedef bucket* link_pointer;
-};
-
-template <typename A, typename T> struct pick_grouped_node
-{
- typedef typename boost::remove_const<T>::type nonconst;
-
- typedef boost::unordered::detail::allocator_traits<
- typename boost::unordered::detail::rebind_wrap<A,
- boost::unordered::detail::grouped_ptr_node<nonconst> >::type>
- tentative_node_traits;
-
- typedef boost::unordered::detail::allocator_traits<
- typename boost::unordered::detail::rebind_wrap<A,
- boost::unordered::detail::ptr_bucket>::type>
- tentative_bucket_traits;
-
- typedef pick_grouped_node2<A, nonconst,
- typename tentative_node_traits::pointer,
- typename tentative_bucket_traits::pointer>
- pick;
-
- typedef typename pick::node node;
- typedef typename pick::bucket bucket;
- typedef typename pick::link_pointer link_pointer;
- typedef boost::unordered::detail::grouped_node_algo<node> node_algo;
-};
-
-template <typename Types>
-struct grouped_table_impl : boost::unordered::detail::table<Types>
-{
- typedef boost::unordered::detail::table<Types> table;
- typedef typename table::value_type value_type;
- typedef typename table::bucket bucket;
- typedef typename table::policy policy;
- typedef typename table::node_pointer node_pointer;
- typedef typename table::node_allocator node_allocator;
- typedef typename table::node_allocator_traits node_allocator_traits;
- typedef typename table::bucket_pointer bucket_pointer;
- typedef typename table::link_pointer link_pointer;
- typedef typename table::hasher hasher;
- typedef typename table::key_equal key_equal;
- typedef typename table::const_key_type const_key_type;
- typedef typename table::node_constructor node_constructor;
- typedef typename table::node_tmp node_tmp;
- typedef typename table::extractor extractor;
- typedef typename table::iterator iterator;
- typedef typename table::c_iterator c_iterator;
- typedef typename table::node_algo node_algo;
-
- // Constructors
-
- grouped_table_impl(std::size_t n, hasher const& hf, key_equal const& eq,
- node_allocator const& a)
- : table(n, hf, eq, a)
- {
- }
-
- grouped_table_impl(grouped_table_impl const& x)
- : table(x, node_allocator_traits::select_on_container_copy_construction(
- x.node_alloc()))
- {
- this->init(x);
- }
-
- grouped_table_impl(grouped_table_impl const& x, node_allocator const& a)
- : table(x, a)
- {
- this->init(x);
- }
-
- grouped_table_impl(
- grouped_table_impl& x, boost::unordered::detail::move_tag m)
- : table(x, m)
- {
- }
-
- grouped_table_impl(grouped_table_impl& x, node_allocator const& a,
- boost::unordered::detail::move_tag m)
- : table(x, a, m)
- {
- this->move_init(x);
}
- // Accessors
-
- std::size_t count(const_key_type& k) const
- {
- node_pointer n = this->find_node(k);
- return n ? node_algo::count(n, this) : 0;
- }
-
- std::pair<iterator, iterator> equal_range(const_key_type& k) const
- {
- node_pointer n = this->find_node(k);
- return std::make_pair(
- iterator(n), iterator(n ? node_algo::next_group(n, this) : n));
- }
+ ////////////////////////////////////////////////////////////////////////
+ // Equivalent keys
// Equality
- bool equals(grouped_table_impl const& other) const
+ bool equals_equiv(table const& other) const
{
if (this->size_ != other.size_)
return false;
for (node_pointer n1 = this->begin(); n1;) {
- node_pointer n2 = other.find_node(other.get_key(n1->value()));
+ node_pointer n2 = other.find_node(other.get_key(n1));
if (!n2)
return false;
- node_pointer end1 = node_algo::next_group(n1, this);
- node_pointer end2 = node_algo::next_group(n2, this);
- if (!group_equals(n1, end1, n2, end2))
+ node_pointer end1 = next_group(n1);
+ node_pointer end2 = next_group(n2);
+ if (!group_equals_equiv(n1, end1, n2, end2))
return false;
n1 = end1;
}
@@ -4522,15 +3820,15 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
return true;
}
- static bool group_equals(
+ static bool group_equals_equiv(
node_pointer n1, node_pointer end1, node_pointer n2, node_pointer end2)
{
for (;;) {
if (n1->value() != n2->value())
break;
- n1 = node_algo::next_node(n1);
- n2 = node_algo::next_node(n2);
+ n1 = next_node(n1);
+ n2 = next_node(n2);
if (n1 == end1)
return n2 == end2;
@@ -4539,8 +3837,8 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
}
for (node_pointer n1a = n1, n2a = n2;;) {
- n1a = node_algo::next_node(n1a);
- n2a = node_algo::next_node(n2a);
+ n1a = next_node(n1a);
+ n2a = next_node(n2a);
if (n1a == end1) {
if (n2a == end2)
@@ -4554,14 +3852,13 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
}
node_pointer start = n1;
- for (; n1 != end1; n1 = node_algo::next_node(n1)) {
+ for (; n1 != end1; n1 = next_node(n1)) {
value_type const& v = n1->value();
- if (!find(start, n1, v)) {
- std::size_t matches = count_equal(n2, end2, v);
+ if (!find_equiv(start, n1, v)) {
+ std::size_t matches = count_equal_equiv(n2, end2, v);
if (!matches)
return false;
- if (matches !=
- 1 + count_equal(node_algo::next_node(n1), end1, v))
+ if (matches != 1 + count_equal_equiv(next_node(n1), end1, v))
return false;
}
}
@@ -4569,19 +3866,20 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
return true;
}
- static bool find(node_pointer n, node_pointer end, value_type const& v)
+ static bool find_equiv(
+ node_pointer n, node_pointer end, value_type const& v)
{
- for (; n != end; n = node_algo::next_node(n))
+ for (; n != end; n = next_node(n))
if (n->value() == v)
return true;
return false;
}
- static std::size_t count_equal(
+ static std::size_t count_equal_equiv(
node_pointer n, node_pointer end, value_type const& v)
{
std::size_t count = 0;
- for (; n != end; n = node_algo::next_node(n))
+ for (; n != end; n = next_node(n))
if (n->value() == v)
++count;
return count;
@@ -4589,29 +3887,31 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
// Emplace/Insert
- inline node_pointer add_node(
+ inline node_pointer add_node_equiv(
node_pointer n, std::size_t key_hash, node_pointer pos)
{
- n->hash_ = key_hash;
+ std::size_t bucket_index = this->hash_to_bucket(key_hash);
+ n->bucket_info_ = bucket_index;
+
if (pos) {
- node_algo::add_to_node_group(n, pos);
+ n->reset_first_in_group();
+ n->next_ = pos->next_;
+ pos->next_ = n;
if (n->next_) {
- std::size_t next_bucket =
- this->hash_to_bucket(node_algo::next_node(n)->hash_);
- if (next_bucket != this->hash_to_bucket(key_hash)) {
+ std::size_t next_bucket = this->node_bucket(next_node(n));
+ if (next_bucket != bucket_index) {
this->get_bucket(next_bucket)->next_ = n;
}
}
} else {
- bucket_pointer b = this->get_bucket(this->hash_to_bucket(key_hash));
+ // n->set_first_in_group();
+ bucket_pointer b = this->get_bucket(bucket_index);
if (!b->next_) {
link_pointer start_node = this->get_previous_start();
if (start_node->next_) {
- this->get_bucket(
- this->hash_to_bucket(
- node_algo::next_node(start_node)->hash_))
+ this->get_bucket(this->node_bucket(next_node(start_node)))
->next_ = n;
}
@@ -4627,14 +3927,15 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
return n;
}
- inline node_pointer add_using_hint(node_pointer n, node_pointer hint)
+ inline node_pointer add_using_hint_equiv(node_pointer n, node_pointer hint)
{
- n->hash_ = hint->hash_;
- node_algo::add_to_node_group(n, hint);
- if (n->next_ != hint && n->next_) {
- std::size_t next_bucket =
- this->hash_to_bucket(node_algo::next_node(n)->hash_);
- if (next_bucket != this->hash_to_bucket(n->hash_)) {
+ n->bucket_info_ = hint->bucket_info_;
+ n->reset_first_in_group();
+ n->next_ = hint->next_;
+ hint->next_ = n;
+ if (n->next_) {
+ std::size_t next_bucket = this->node_bucket(next_node(n));
+ if (next_bucket != this->node_bucket(n)) {
this->get_bucket(next_bucket)->next_ = n;
}
}
@@ -4642,100 +3943,53 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
return n;
}
-#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
-#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- iterator emplace(boost::unordered::detail::emplace_args1<
- boost::unordered::detail::please_ignore_this_overload> const&)
- {
- BOOST_ASSERT(false);
- return iterator();
- }
-
- iterator emplace_hint(
- c_iterator,
- boost::unordered::detail::emplace_args1<
- boost::unordered::detail::please_ignore_this_overload> const&)
- {
- BOOST_ASSERT(false);
- return iterator();
- }
-#else
- iterator emplace(
- boost::unordered::detail::please_ignore_this_overload const&)
- {
- BOOST_ASSERT(false);
- return iterator();
- }
-
- iterator emplace_hint(c_iterator,
- boost::unordered::detail::please_ignore_this_overload const&)
- {
- BOOST_ASSERT(false);
- return iterator();
- }
-#endif
-#endif
-
- template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
- iterator emplace(BOOST_UNORDERED_EMPLACE_ARGS)
- {
- return iterator(emplace_impl(
- boost::unordered::detail::func::construct_node_from_args(
- this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD)));
- }
-
- template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
- iterator emplace_hint(c_iterator hint, BOOST_UNORDERED_EMPLACE_ARGS)
- {
- return iterator(emplace_hint_impl(
- hint, boost::unordered::detail::func::construct_node_from_args(
- this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD)));
- }
-
- iterator emplace_impl(node_pointer n)
+ iterator emplace_equiv(node_pointer n)
{
node_tmp a(n, this->node_alloc());
- const_key_type& k = this->get_key(a.node_->value());
+ const_key_type& k = this->get_key(a.node_);
std::size_t key_hash = this->hash(k);
node_pointer position = this->find_node(key_hash, k);
this->reserve_for_insert(this->size_ + 1);
- return iterator(this->add_node(a.release(), key_hash, position));
+ return iterator(this->add_node_equiv(a.release(), key_hash, position));
}
- iterator emplace_hint_impl(c_iterator hint, node_pointer n)
+ iterator emplace_hint_equiv(c_iterator hint, node_pointer n)
{
node_tmp a(n, this->node_alloc());
- const_key_type& k = this->get_key(a.node_->value());
- if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
+ const_key_type& k = this->get_key(a.node_);
+ if (hint.node_ && this->key_eq()(k, this->get_key(hint.node_))) {
this->reserve_for_insert(this->size_ + 1);
- return iterator(this->add_using_hint(a.release(), hint.node_));
+ return iterator(
+ this->add_using_hint_equiv(a.release(), hint.node_));
} else {
std::size_t key_hash = this->hash(k);
node_pointer position = this->find_node(key_hash, k);
this->reserve_for_insert(this->size_ + 1);
- return iterator(this->add_node(a.release(), key_hash, position));
+ return iterator(
+ this->add_node_equiv(a.release(), key_hash, position));
}
}
- void emplace_impl_no_rehash(node_pointer n)
+ void emplace_no_rehash_equiv(node_pointer n)
{
node_tmp a(n, this->node_alloc());
- const_key_type& k = this->get_key(a.node_->value());
+ const_key_type& k = this->get_key(a.node_);
std::size_t key_hash = this->hash(k);
node_pointer position = this->find_node(key_hash, k);
- this->add_node(a.release(), key_hash, position);
+ this->add_node_equiv(a.release(), key_hash, position);
}
- template <typename NodeType> iterator move_insert_node_type(NodeType& np)
+ template <typename NodeType>
+ iterator move_insert_node_type_equiv(NodeType& np)
{
iterator result;
if (np) {
- const_key_type& k = this->get_key(np.ptr_->value());
+ const_key_type& k = this->get_key(np.ptr_);
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
this->reserve_for_insert(this->size_ + 1);
- result = iterator(this->add_node(np.ptr_, key_hash, pos));
+ result = iterator(this->add_node_equiv(np.ptr_, key_hash, pos));
np.ptr_ = node_pointer();
}
@@ -4743,21 +3997,23 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
}
template <typename NodeType>
- iterator move_insert_node_type_with_hint(c_iterator hint, NodeType& np)
+ iterator move_insert_node_type_with_hint_equiv(
+ c_iterator hint, NodeType& np)
{
iterator result;
if (np) {
- const_key_type& k = this->get_key(np.ptr_->value());
+ const_key_type& k = this->get_key(np.ptr_);
- if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
+ if (hint.node_ && this->key_eq()(k, this->get_key(hint.node_))) {
this->reserve_for_insert(this->size_ + 1);
- result = iterator(this->add_using_hint(np.ptr_, hint.node_));
+ result =
+ iterator(this->add_using_hint_equiv(np.ptr_, hint.node_));
} else {
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
this->reserve_for_insert(this->size_ + 1);
- result = iterator(this->add_node(np.ptr_, key_hash, pos));
+ result = iterator(this->add_node_equiv(np.ptr_, key_hash, pos));
}
np.ptr_ = node_pointer();
}
@@ -4771,7 +4027,7 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
// if hash function throws, or inserting > 1 element, basic exception
// safety. Strong otherwise
template <class I>
- void insert_range(I i, I j,
+ void insert_range_equiv(I i, I j,
typename boost::unordered::detail::enable_if_forward<I, void*>::type =
0)
{
@@ -4780,14 +4036,14 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
std::size_t distance = static_cast<std::size_t>(std::distance(i, j));
if (distance == 1) {
- emplace_impl(boost::unordered::detail::func::construct_node(
+ emplace_equiv(boost::unordered::detail::func::construct_node(
this->node_alloc(), *i));
} else {
// Only require basic exception safety here
this->reserve_for_insert(this->size_ + distance);
for (; i != j; ++i) {
- emplace_impl_no_rehash(
+ emplace_no_rehash_equiv(
boost::unordered::detail::func::construct_node(
this->node_alloc(), *i));
}
@@ -4795,12 +4051,12 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
}
template <class I>
- void insert_range(I i, I j,
+ void insert_range_equiv(I i, I j,
typename boost::unordered::detail::disable_if_forward<I, void*>::type =
0)
{
for (; i != j; ++i) {
- emplace_impl(boost::unordered::detail::func::construct_node(
+ emplace_equiv(boost::unordered::detail::func::construct_node(
this->node_alloc(), *i));
}
}
@@ -4808,30 +4064,24 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
////////////////////////////////////////////////////////////////////////
// Extract
- inline node_pointer extract_by_iterator(c_iterator n)
+ inline node_pointer extract_by_iterator_equiv(c_iterator n)
{
node_pointer i = n.node_;
BOOST_ASSERT(i);
- node_pointer j(node_algo::next_node(i));
- std::size_t bucket_index = this->hash_to_bucket(i->hash_);
- // Split the groups containing 'i' and 'j'.
- // And get the pointer to the node before i while
- // we're at it.
- link_pointer prev = node_algo::split_groups(i, j);
-
- // If we don't have a 'prev' it means that i is at the
- // beginning of a block, so search through the blocks in the
- // same bucket.
- if (!prev) {
- prev = this->get_previous_start(bucket_index);
- while (prev->next_ != i) {
- prev = node_algo::next_for_erase(prev);
- }
+ node_pointer j(next_node(i));
+ std::size_t bucket_index = this->node_bucket(i);
+
+ link_pointer prev = this->get_previous_start(bucket_index);
+ while (prev->next_ != i) {
+ prev = next_node(prev);
}
- prev->next_ = i->next_;
+ prev->next_ = j;
+ if (j && i->is_first_in_group()) {
+ j->set_first_in_group();
+ }
--this->size_;
- this->fix_bucket(bucket_index, prev);
+ this->fix_bucket(bucket_index, prev, j);
i->next_ = link_pointer();
return i;
@@ -4842,66 +4092,55 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
//
// no throw
- std::size_t erase_key(const_key_type& k)
+ std::size_t erase_key_equiv(const_key_type& k)
{
if (!this->size_)
return 0;
std::size_t key_hash = this->hash(k);
std::size_t bucket_index = this->hash_to_bucket(key_hash);
- link_pointer prev = this->find_previous_node(k, key_hash, bucket_index);
+ link_pointer prev = this->find_previous_node(k, bucket_index);
if (!prev)
return 0;
- node_pointer first_node = node_algo::next_node(prev);
- link_pointer end = node_algo::next_group(first_node, this);
-
- std::size_t deleted_count = this->delete_nodes(prev, end);
- this->fix_bucket(bucket_index, prev);
+ std::size_t deleted_count = 0;
+ node_pointer n = next_node(prev);
+ do {
+ node_pointer n2 = next_node(n);
+ destroy_node(n);
+ ++deleted_count;
+ n = n2;
+ } while (n && !n->is_first_in_group());
+ size_ -= deleted_count;
+ prev->next_ = n;
+ this->fix_bucket(bucket_index, prev, n);
return deleted_count;
}
- iterator erase(c_iterator r)
+ link_pointer erase_nodes_equiv(node_pointer i, node_pointer j)
{
- BOOST_ASSERT(r.node_);
- node_pointer next = node_algo::next_node(r.node_);
- erase_nodes(r.node_, next);
- return iterator(next);
- }
+ std::size_t bucket_index = this->node_bucket(i);
- iterator erase_range(c_iterator r1, c_iterator r2)
- {
- if (r1 == r2)
- return iterator(r2.node_);
- erase_nodes(r1.node_, r2.node_);
- return iterator(r2.node_);
- }
-
- link_pointer erase_nodes(node_pointer i, node_pointer j)
- {
- std::size_t bucket_index = this->hash_to_bucket(i->hash_);
-
- // Split the groups containing 'i' and 'j'.
- // And get the pointer to the node before i while
- // we're at it.
- link_pointer prev = node_algo::split_groups(i, j);
-
- // If we don't have a 'prev' it means that i is at the
- // beginning of a block, so search through the blocks in the
- // same bucket.
- if (!prev) {
- prev = this->get_previous_start(bucket_index);
- while (prev->next_ != i) {
- prev = node_algo::next_for_erase(prev);
- }
+ link_pointer prev = this->get_previous_start(bucket_index);
+ while (prev->next_ != i) {
+ prev = next_node(prev);
}
// Delete the nodes.
// Is it inefficient to call fix_bucket for every node?
+ bool includes_first = false;
+ prev->next_ = j;
do {
- this->delete_node(prev);
- bucket_index = this->fix_bucket(bucket_index, prev);
- } while (prev->next_ != j);
+ includes_first = includes_first || i->is_first_in_group();
+ node_pointer next = next_node(i);
+ destroy_node(i);
+ --size_;
+ bucket_index = this->fix_bucket(bucket_index, prev, next);
+ i = next;
+ } while (i != j);
+ if (j && includes_first) {
+ j->set_first_in_group();
+ }
return prev;
}
@@ -4909,78 +4148,504 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
////////////////////////////////////////////////////////////////////////
// fill_buckets
- void copy_buckets(table const& src)
+ void copy_buckets(table const& src, false_type)
{
this->create_buckets(this->bucket_count_);
for (node_pointer n = src.begin(); n;) {
- std::size_t key_hash = n->hash_;
- node_pointer group_end(node_algo::next_group(n, this));
- node_pointer pos =
- this->add_node(boost::unordered::detail::func::construct_node(
- this->node_alloc(), n->value()),
- key_hash, node_pointer());
- for (n = node_algo::next_node(n); n != group_end;
- n = node_algo::next_node(n)) {
- this->add_node(boost::unordered::detail::func::construct_node(
- this->node_alloc(), n->value()),
+ std::size_t key_hash = this->hash(this->get_key(n));
+ node_pointer group_end(next_group(n));
+ node_pointer pos = this->add_node_equiv(
+ boost::unordered::detail::func::construct_node(
+ this->node_alloc(), n->value()),
+ key_hash, node_pointer());
+ for (n = next_node(n); n != group_end; n = next_node(n)) {
+ this->add_node_equiv(
+ boost::unordered::detail::func::construct_node(
+ this->node_alloc(), n->value()),
key_hash, pos);
}
}
}
- void move_buckets(table const& src)
+ void move_buckets_equiv(table const& src)
{
this->create_buckets(this->bucket_count_);
for (node_pointer n = src.begin(); n;) {
- std::size_t key_hash = n->hash_;
- node_pointer group_end(node_algo::next_group(n, this));
- node_pointer pos =
- this->add_node(boost::unordered::detail::func::construct_node(
- this->node_alloc(), boost::move(n->value())),
- key_hash, node_pointer());
- for (n = node_algo::next_node(n); n != group_end;
- n = node_algo::next_node(n)) {
- this->add_node(boost::unordered::detail::func::construct_node(
- this->node_alloc(), boost::move(n->value())),
+ std::size_t key_hash = this->hash(this->get_key(n));
+ node_pointer group_end(next_group(n));
+ node_pointer pos = this->add_node_equiv(
+ boost::unordered::detail::func::construct_node(
+ this->node_alloc(), boost::move(n->value())),
+ key_hash, node_pointer());
+ for (n = next_node(n); n != group_end; n = next_node(n)) {
+ this->add_node_equiv(
+ boost::unordered::detail::func::construct_node(
+ this->node_alloc(), boost::move(n->value())),
key_hash, pos);
}
}
}
- void assign_buckets(table const& src)
+ void assign_buckets(table const& src, false_type)
{
node_holder<node_allocator> holder(*this);
for (node_pointer n = src.begin(); n;) {
- std::size_t key_hash = n->hash_;
- node_pointer group_end(node_algo::next_group(n, this));
- node_pointer pos = this->add_node(
+ std::size_t key_hash = this->hash(this->get_key(n));
+ node_pointer group_end(next_group(n));
+ node_pointer pos = this->add_node_equiv(
holder.copy_of(n->value()), key_hash, node_pointer());
- for (n = node_algo::next_node(n); n != group_end;
- n = node_algo::next_node(n)) {
- this->add_node(holder.copy_of(n->value()), key_hash, pos);
+ for (n = next_node(n); n != group_end; n = next_node(n)) {
+ this->add_node_equiv(holder.copy_of(n->value()), key_hash, pos);
}
}
}
- void move_assign_buckets(table& src)
+ void move_assign_buckets(table& src, false_type)
{
node_holder<node_allocator> holder(*this);
for (node_pointer n = src.begin(); n;) {
- std::size_t key_hash = n->hash_;
- node_pointer group_end(node_algo::next_group(n, this));
- node_pointer pos = this->add_node(
+ std::size_t key_hash = this->hash(this->get_key(n));
+ node_pointer group_end(next_group(n));
+ node_pointer pos = this->add_node_equiv(
holder.move_copy_of(n->value()), key_hash, node_pointer());
- for (n = node_algo::next_node(n); n != group_end;
- n = node_algo::next_node(n)) {
- this->add_node(holder.move_copy_of(n->value()), key_hash, pos);
+ for (n = next_node(n); n != group_end; n = next_node(n)) {
+ this->add_node_equiv(
+ holder.move_copy_of(n->value()), key_hash, pos);
+ }
+ }
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////
+// Clear
+
+template <typename Types> inline void table<Types>::clear_impl()
+{
+ if (size_) {
+ bucket_pointer end = get_bucket(bucket_count_);
+ for (bucket_pointer it = buckets_; it != end; ++it) {
+ it->next_ = node_pointer();
+ }
+
+ link_pointer prev = end->first_from_start();
+ node_pointer n = next_node(prev);
+ prev->next_ = node_pointer();
+ size_ = 0;
+
+ while (n) {
+ node_pointer next = next_node(n);
+ destroy_node(n);
+ n = next;
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Reserve & Rehash
+
+// basic exception safety
+template <typename Types>
+inline void table<Types>::reserve_for_insert(std::size_t size)
+{
+ if (!buckets_) {
+ create_buckets((std::max)(bucket_count_, min_buckets_for_size(size)));
+ } else if (size > max_load_) {
+ std::size_t num_buckets =
+ min_buckets_for_size((std::max)(size, size_ + (size_ >> 1)));
+
+ if (num_buckets != bucket_count_)
+ this->rehash_impl(num_buckets);
+ }
+}
+
+// if hash function throws, basic exception safety
+// strong otherwise.
+
+template <typename Types>
+inline void table<Types>::rehash(std::size_t min_buckets)
+{
+ using namespace std;
+
+ if (!size_) {
+ delete_buckets();
+ bucket_count_ = policy::new_bucket_count(min_buckets);
+ } else {
+ min_buckets = policy::new_bucket_count((std::max)(min_buckets,
+ boost::unordered::detail::double_to_size(
+ floor(static_cast<double>(size_) / static_cast<double>(mlf_))) +
+ 1));
+
+ if (min_buckets != bucket_count_)
+ this->rehash_impl(min_buckets);
+ }
+}
+
+template <typename Types>
+inline void table<Types>::rehash_impl(std::size_t num_buckets)
+{
+ BOOST_ASSERT(this->buckets_);
+
+ this->create_buckets(num_buckets);
+ link_pointer prev = this->get_previous_start();
+ BOOST_TRY
+ {
+ while (prev->next_) {
+ node_pointer n = next_node(prev);
+ std::size_t key_hash = this->hash(this->get_key(n));
+ std::size_t bucket_index = this->hash_to_bucket(key_hash);
+
+ n->bucket_info_ = bucket_index;
+ n->set_first_in_group();
+
+ // Iterator through the rest of the group of equal nodes,
+ // setting the bucket.
+ for (;;) {
+ node_pointer next = next_node(n);
+ if (!next || next->is_first_in_group()) {
+ break;
+ }
+ n = next;
+ n->bucket_info_ = bucket_index;
+ n->reset_first_in_group();
+ }
+
+ // n is now the last node in the group
+ bucket_pointer b = this->get_bucket(bucket_index);
+ if (!b->next_) {
+ b->next_ = prev;
+ prev = n;
+ } else {
+ link_pointer next = n->next_;
+ n->next_ = b->next_->next_;
+ b->next_->next_ = prev->next_;
+ prev->next_ = next;
}
}
}
+ BOOST_CATCH(...)
+ {
+ node_pointer n = next_node(prev);
+ prev->next_ = node_pointer();
+ while (n) {
+ node_pointer next = next_node(n);
+ destroy_node(n);
+ --size_;
+ n = next;
+ }
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+}
+
+#if defined(BOOST_MSVC)
+#pragma warning(pop)
+#endif
+
+////////////////////////////////////////////////////////////////////////
+// key extractors
+//
+// no throw
+//
+// 'extract_key' is called with the emplace parameters to return a
+// key if available or 'no_key' is one isn't and will need to be
+// constructed. This could be done by overloading the emplace implementation
+// for the different cases, but that's a bit tricky on compilers without
+// variadic templates.
+
+template <typename Key, typename T> struct is_key
+{
+ template <typename T2> static choice1::type test(T2 const&);
+ static choice2::type test(Key const&);
+
+ enum
+ {
+ value = sizeof(test(boost::unordered::detail::make<T>())) ==
+ sizeof(choice2::type)
+ };
+
+ typedef typename boost::detail::if_true<value>::BOOST_NESTED_TEMPLATE
+ then<Key const&, no_key>::type type;
+};
+
+template <class ValueType> struct set_extractor
+{
+ typedef ValueType value_type;
+ typedef ValueType key_type;
+
+ static key_type const& extract(value_type const& v) { return v; }
+
+ static key_type const& extract(BOOST_UNORDERED_RV_REF(value_type) v)
+ {
+ return v;
+ }
+
+ static no_key extract() { return no_key(); }
+
+ template <class Arg> static no_key extract(Arg const&) { return no_key(); }
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template <class Arg1, class Arg2, class... Args>
+ static no_key extract(Arg1 const&, Arg2 const&, Args const&...)
+ {
+ return no_key();
+ }
+#else
+ template <class Arg1, class Arg2>
+ static no_key extract(Arg1 const&, Arg2 const&)
+ {
+ return no_key();
+ }
+#endif
+};
+
+template <class ValueType> struct map_extractor
+{
+ typedef ValueType value_type;
+ typedef typename boost::remove_const<typename boost::unordered::detail::
+ pair_traits<ValueType>::first_type>::type key_type;
+
+ static key_type const& extract(value_type const& v) { return v.first; }
+
+ template <class Second>
+ static key_type const& extract(std::pair<key_type, Second> const& v)
+ {
+ return v.first;
+ }
+
+ template <class Second>
+ static key_type const& extract(std::pair<key_type const, Second> const& v)
+ {
+ return v.first;
+ }
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <class Second>
+ static key_type const& extract(
+ boost::rv<std::pair<key_type, Second> > const& v)
+ {
+ return v.first;
+ }
+
+ template <class Second>
+ static key_type const& extract(
+ boost::rv<std::pair<key_type const, Second> > const& v)
+ {
+ return v.first;
+ }
+#endif
+
+ template <class Arg1>
+ static key_type const& extract(key_type const& k, Arg1 const&)
+ {
+ return k;
+ }
+
+ static no_key extract() { return no_key(); }
+
+ template <class Arg> static no_key extract(Arg const&) { return no_key(); }
+
+ template <class Arg1, class Arg2>
+ static no_key extract(Arg1 const&, Arg2 const&)
+ {
+ return no_key();
+ }
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template <class Arg1, class Arg2, class Arg3, class... Args>
+ static no_key extract(Arg1 const&, Arg2 const&, Arg3 const&, Args const&...)
+ {
+ return no_key();
+ }
+#endif
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
+ template <typename T2> \
+ static no_key extract(boost::unordered::piecewise_construct_t, \
+ namespace_ tuple<> const&, T2 const&) \
+ { \
+ return no_key(); \
+ } \
+ \
+ template <typename T, typename T2> \
+ static typename is_key<key_type, T>::type extract( \
+ boost::unordered::piecewise_construct_t, namespace_ tuple<T> const& k, \
+ T2 const&) \
+ { \
+ return typename is_key<key_type, T>::type(namespace_ get<0>(k)); \
+ }
+
+#else
+
+#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
+ static no_key extract( \
+ boost::unordered::piecewise_construct_t, namespace_ tuple<> const&) \
+ { \
+ return no_key(); \
+ } \
+ \
+ template <typename T> \
+ static typename is_key<key_type, T>::type extract( \
+ boost::unordered::piecewise_construct_t, namespace_ tuple<T> const& k) \
+ { \
+ return typename is_key<key_type, T>::type(namespace_ get<0>(k)); \
+ }
+
+#endif
+
+ BOOST_UNORDERED_KEY_FROM_TUPLE(boost::)
+
+#if BOOST_UNORDERED_TUPLE_ARGS
+ BOOST_UNORDERED_KEY_FROM_TUPLE(std::)
+#endif
+
+#undef BOOST_UNORDERED_KEY_FROM_TUPLE
+};
+
+////////////////////////////////////////////////////////////////////////
+// Unique nodes
+
+template <typename A, typename T>
+struct node : boost::unordered::detail::value_base<T>
+{
+ typedef typename ::boost::unordered::detail::rebind_wrap<A,
+ node<A, T> >::type allocator;
+ typedef typename ::boost::unordered::detail::allocator_traits<
+ allocator>::pointer node_pointer;
+ typedef node_pointer link_pointer;
+ typedef typename ::boost::unordered::detail::rebind_wrap<A,
+ bucket<node_pointer> >::type bucket_allocator;
+ typedef typename ::boost::unordered::detail::allocator_traits<
+ bucket_allocator>::pointer bucket_pointer;
+
+ link_pointer next_;
+ std::size_t bucket_info_;
+
+ node() : next_(), bucket_info_(0) {}
+
+ std::size_t get_bucket() const
+ {
+ return bucket_info_ & ((std::size_t)-1 >> 1);
+ }
+
+ std::size_t is_first_in_group() const
+ {
+ return !(bucket_info_ & ~((std::size_t)-1 >> 1));
+ }
+
+ void set_first_in_group()
+ {
+ bucket_info_ = bucket_info_ & ((std::size_t)-1 >> 1);
+ }
+
+ void reset_first_in_group()
+ {
+ bucket_info_ = bucket_info_ | ~((std::size_t)-1 >> 1);
+ }
+
+ private:
+ node& operator=(node const&);
+};
+
+template <typename T> struct ptr_node : boost::unordered::detail::ptr_bucket
+{
+ typedef T value_type;
+ typedef boost::unordered::detail::ptr_bucket bucket_base;
+ typedef ptr_node<T>* node_pointer;
+ typedef ptr_bucket* link_pointer;
+ typedef ptr_bucket* bucket_pointer;
+
+ std::size_t bucket_info_;
+ boost::unordered::detail::value_base<T> value_base_;
+
+ ptr_node() : bucket_base(), bucket_info_(0) {}
+
+ void* address() { return value_base_.address(); }
+ value_type& value() { return value_base_.value(); }
+ value_type* value_ptr() { return value_base_.value_ptr(); }
+
+ std::size_t get_bucket() const
+ {
+ return bucket_info_ & ((std::size_t)-1 >> 1);
+ }
+
+ std::size_t is_first_in_group() const
+ {
+ return !(bucket_info_ & ~((std::size_t)-1 >> 1));
+ }
+
+ void set_first_in_group()
+ {
+ bucket_info_ = bucket_info_ & ((std::size_t)-1 >> 1);
+ }
+
+ void reset_first_in_group()
+ {
+ bucket_info_ = bucket_info_ | ~((std::size_t)-1 >> 1);
+ }
+
+ private:
+ ptr_node& operator=(ptr_node const&);
+};
+
+// If the allocator uses raw pointers use ptr_node
+// Otherwise use node.
+
+template <typename A, typename T, typename NodePtr, typename BucketPtr>
+struct pick_node2
+{
+ typedef boost::unordered::detail::node<A, T> node;
+
+ typedef typename boost::unordered::detail::allocator_traits<
+ typename boost::unordered::detail::rebind_wrap<A, node>::type>::pointer
+ node_pointer;
+
+ typedef boost::unordered::detail::bucket<node_pointer> bucket;
+ typedef node_pointer link_pointer;
+};
+
+template <typename A, typename T>
+struct pick_node2<A, T, boost::unordered::detail::ptr_node<T>*,
+ boost::unordered::detail::ptr_bucket*>
+{
+ typedef boost::unordered::detail::ptr_node<T> node;
+ typedef boost::unordered::detail::ptr_bucket bucket;
+ typedef bucket* link_pointer;
+};
+
+template <typename A, typename T> struct pick_node
+{
+ typedef typename boost::remove_const<T>::type nonconst;
+
+ typedef boost::unordered::detail::allocator_traits<
+ typename boost::unordered::detail::rebind_wrap<A,
+ boost::unordered::detail::ptr_node<nonconst> >::type>
+ tentative_node_traits;
+
+ typedef boost::unordered::detail::allocator_traits<
+ typename boost::unordered::detail::rebind_wrap<A,
+ boost::unordered::detail::ptr_bucket>::type>
+ tentative_bucket_traits;
+
+ typedef pick_node2<A, nonconst, typename tentative_node_traits::pointer,
+ typename tentative_bucket_traits::pointer>
+ pick;
+
+ typedef typename pick::node node;
+ typedef typename pick::bucket bucket;
+ typedef typename pick::link_pointer link_pointer;
};
}
}
}
+#undef BOOST_UNORDERED_EMPLACE_TEMPLATE
+#undef BOOST_UNORDERED_EMPLACE_ARGS
+#undef BOOST_UNORDERED_EMPLACE_FORWARD
+#undef BOOST_UNORDERED_CALL_CONSTRUCT1
+#undef BOOST_UNORDERED_CALL_DESTROY
+
#endif
diff --git a/boost/unordered/detail/map.hpp b/boost/unordered/detail/map.hpp
index cb9a954bb2..172b4f4b61 100644
--- a/boost/unordered/detail/map.hpp
+++ b/boost/unordered/detail/map.hpp
@@ -27,65 +27,22 @@ template <typename A, typename K, typename M, typename H, typename P> struct map
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
- typedef typename pick::node_algo node_algo;
- typedef boost::unordered::detail::table_impl<types> table;
+ typedef boost::unordered::detail::table<types> table;
typedef boost::unordered::detail::map_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
typedef boost::unordered::iterator_detail::iterator<node> iterator;
typedef boost::unordered::iterator_detail::c_iterator<node> c_iterator;
- typedef boost::unordered::iterator_detail::l_iterator<node, policy>
- l_iterator;
- typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
- cl_iterator;
+ typedef boost::unordered::iterator_detail::l_iterator<node> l_iterator;
+ typedef boost::unordered::iterator_detail::cl_iterator<node> cl_iterator;
typedef boost::unordered::node_handle_map<node, K, M, A> node_type;
typedef boost::unordered::insert_return_type_map<node, K, M, A>
insert_return_type;
};
-template <typename A, typename K, typename M, typename H, typename P>
-struct multimap
-{
- typedef boost::unordered::detail::multimap<A, K, M, H, P> types;
-
- typedef std::pair<K const, M> value_type;
- typedef H hasher;
- typedef P key_equal;
- typedef K const const_key_type;
-
- typedef typename ::boost::unordered::detail::rebind_wrap<A,
- value_type>::type value_allocator;
- typedef boost::unordered::detail::allocator_traits<value_allocator>
- value_allocator_traits;
-
-#if BOOST_UNORDERED_INTEROPERABLE_NODES
- typedef boost::unordered::detail::pick_node<A, value_type> pick;
-#else
- typedef boost::unordered::detail::pick_grouped_node<A, value_type> pick;
-#endif
- typedef typename pick::node node;
- typedef typename pick::bucket bucket;
- typedef typename pick::link_pointer link_pointer;
- typedef typename pick::node_algo node_algo;
-
- typedef boost::unordered::detail::grouped_table_impl<types> table;
- typedef boost::unordered::detail::map_extractor<value_type> extractor;
-
- typedef typename boost::unordered::detail::pick_policy<K>::type policy;
-
- typedef boost::unordered::iterator_detail::iterator<node> iterator;
- typedef boost::unordered::iterator_detail::c_iterator<node> c_iterator;
- typedef boost::unordered::iterator_detail::l_iterator<node, policy>
- l_iterator;
- typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
- cl_iterator;
-
- typedef boost::unordered::node_handle_map<node, K, M, A> node_type;
-};
-
template <typename K, typename M, typename H, typename P, typename A>
class instantiate_map
{
diff --git a/boost/unordered/detail/set.hpp b/boost/unordered/detail/set.hpp
index 42e9cad7b5..a164991776 100644
--- a/boost/unordered/detail/set.hpp
+++ b/boost/unordered/detail/set.hpp
@@ -27,64 +27,22 @@ template <typename A, typename T, typename H, typename P> struct set
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
- typedef typename pick::node_algo node_algo;
- typedef boost::unordered::detail::table_impl<types> table;
+ typedef boost::unordered::detail::table<types> table;
typedef boost::unordered::detail::set_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<T>::type policy;
typedef boost::unordered::iterator_detail::c_iterator<node> iterator;
typedef boost::unordered::iterator_detail::c_iterator<node> c_iterator;
- typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
- l_iterator;
- typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
- cl_iterator;
+ typedef boost::unordered::iterator_detail::cl_iterator<node> l_iterator;
+ typedef boost::unordered::iterator_detail::cl_iterator<node> cl_iterator;
typedef boost::unordered::node_handle_set<node, T, A> node_type;
typedef boost::unordered::insert_return_type_set<node, T, A>
insert_return_type;
};
-template <typename A, typename T, typename H, typename P> struct multiset
-{
- typedef boost::unordered::detail::multiset<A, T, H, P> types;
-
- typedef T value_type;
- typedef H hasher;
- typedef P key_equal;
- typedef T const const_key_type;
-
- typedef typename ::boost::unordered::detail::rebind_wrap<A,
- value_type>::type value_allocator;
- typedef boost::unordered::detail::allocator_traits<value_allocator>
- value_allocator_traits;
-
-#if BOOST_UNORDERED_INTEROPERABLE_NODES
- typedef boost::unordered::detail::pick_node<A, value_type> pick;
-#else
- typedef boost::unordered::detail::pick_grouped_node<A, value_type> pick;
-#endif
- typedef typename pick::node node;
- typedef typename pick::bucket bucket;
- typedef typename pick::link_pointer link_pointer;
- typedef typename pick::node_algo node_algo;
-
- typedef boost::unordered::detail::grouped_table_impl<types> table;
- typedef boost::unordered::detail::set_extractor<value_type> extractor;
-
- typedef typename boost::unordered::detail::pick_policy<T>::type policy;
-
- typedef boost::unordered::iterator_detail::c_iterator<node> iterator;
- typedef boost::unordered::iterator_detail::c_iterator<node> c_iterator;
- typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
- l_iterator;
- typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
- cl_iterator;
-
- typedef boost::unordered::node_handle_set<node, T, A> node_type;
-};
-
template <typename T, typename H, typename P, typename A> class instantiate_set
{
typedef boost::unordered_set<T, H, P, A> container;
diff --git a/boost/unordered/unordered_map.hpp b/boost/unordered/unordered_map.hpp
index 64e5b1fdf8..a0b4d53292 100644
--- a/boost/unordered/unordered_map.hpp
+++ b/boost/unordered/unordered_map.hpp
@@ -17,6 +17,7 @@
#include <boost/core/explicit_operator_bool.hpp>
#include <boost/functional/hash.hpp>
#include <boost/move/move.hpp>
+#include <boost/type_traits/is_constructible.hpp>
#include <boost/unordered/detail/map.hpp>
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@@ -44,8 +45,8 @@ template <class K, class T, class H, class P, class A> class unordered_map
public:
typedef K key_type;
- typedef std::pair<const K, T> value_type;
typedef T mapped_type;
+ typedef std::pair<const K, T> value_type;
typedef H hasher;
typedef P key_equal;
typedef A allocator_type;
@@ -54,6 +55,8 @@ template <class K, class T, class H, class P, class A> class unordered_map
typedef boost::unordered::detail::map<A, K, T, H, P> types;
typedef typename types::value_allocator_traits value_allocator_traits;
typedef typename types::table table;
+ typedef typename table::node_pointer node_pointer;
+ typedef typename table::link_pointer link_pointer;
public:
typedef typename value_allocator_traits::pointer pointer;
@@ -65,10 +68,10 @@ template <class K, class T, class H, class P, class A> class unordered_map
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
- typedef typename table::cl_iterator const_local_iterator;
- typedef typename table::l_iterator local_iterator;
- typedef typename table::c_iterator const_iterator;
typedef typename table::iterator iterator;
+ typedef typename table::c_iterator const_iterator;
+ typedef typename table::l_iterator local_iterator;
+ typedef typename table::cl_iterator const_local_iterator;
typedef typename types::node_type node_type;
typedef typename types::insert_return_type insert_return_type;
@@ -84,59 +87,54 @@ template <class K, class T, class H, class P, class A> class unordered_map
const key_equal& = key_equal(),
const allocator_type& = allocator_type());
- explicit unordered_map(size_type, const allocator_type&);
-
- explicit unordered_map(size_type, const hasher&, const allocator_type&);
-
- explicit unordered_map(allocator_type const&);
-
- template <class InputIt> unordered_map(InputIt, InputIt);
-
- template <class InputIt>
- unordered_map(InputIt, InputIt, size_type, const hasher& = hasher(),
- const key_equal& = key_equal());
-
template <class InputIt>
- unordered_map(InputIt, InputIt, size_type, const hasher&, const key_equal&,
- const allocator_type&);
-
- template <class InputIt>
- unordered_map(
- InputIt, InputIt, size_type, const hasher&, const allocator_type&);
-
- template <class InputIt>
- unordered_map(InputIt, InputIt, size_type, const allocator_type&);
-
- // copy/move constructors
+ unordered_map(InputIt, InputIt,
+ size_type = boost::unordered::detail::default_bucket_count,
+ const hasher& = hasher(), const key_equal& = key_equal(),
+ const allocator_type& = allocator_type());
unordered_map(unordered_map const&);
- unordered_map(unordered_map const&, allocator_type const&);
- unordered_map(BOOST_RV_REF(unordered_map), allocator_type const&);
-
-#if defined(BOOST_UNORDERED_USE_MOVE)
+#if defined(BOOST_UNORDERED_USE_MOVE) || \
+ !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_map(BOOST_RV_REF(unordered_map) other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
- }
-#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- unordered_map(unordered_map&& other)
- BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
- : table_(other.table_, boost::unordered::detail::move_tag())
- {
+ // The move is done in table_
}
#endif
+ explicit unordered_map(allocator_type const&);
+
+ unordered_map(unordered_map const&, allocator_type const&);
+
+ unordered_map(BOOST_RV_REF(unordered_map), allocator_type const&);
+
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_map(std::initializer_list<value_type>,
size_type = boost::unordered::detail::default_bucket_count,
const hasher& = hasher(), const key_equal& l = key_equal(),
const allocator_type& = allocator_type());
- unordered_map(std::initializer_list<value_type>, size_type, const hasher&,
- const allocator_type&);
+#endif
+
+ explicit unordered_map(size_type, const allocator_type&);
+
+ explicit unordered_map(size_type, const hasher&, const allocator_type&);
+
+ template <class InputIt>
+ unordered_map(InputIt, InputIt, size_type, const allocator_type&);
+
+ template <class InputIt>
+ unordered_map(
+ InputIt, InputIt, size_type, const hasher&, const allocator_type&);
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_map(
std::initializer_list<value_type>, size_type, const allocator_type&);
+
+ unordered_map(std::initializer_list<value_type>, size_type, const hasher&,
+ const allocator_type&);
#endif
// Destructor
@@ -148,26 +146,34 @@ template <class K, class T, class H, class P, class A> class unordered_map
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_map& operator=(BOOST_COPY_ASSIGN_REF(unordered_map) x)
{
- table_.assign(x.table_);
+ table_.assign(x.table_, boost::unordered::detail::true_type());
return *this;
}
unordered_map& operator=(BOOST_RV_REF(unordered_map) x)
+ // C++17 support: BOOST_NOEXCEPT_IF(
+ // value_allocator_traits::is_always_equal::value &&
+ // is_nothrow_move_assignable_v<H> &&
+ // is_nothrow_move_assignable_v<P>)
{
- table_.move_assign(x.table_);
+ table_.move_assign(x.table_, boost::unordered::detail::true_type());
return *this;
}
#else
unordered_map& operator=(unordered_map const& x)
{
- table_.assign(x.table_);
+ table_.assign(x.table_, boost::unordered::detail::true_type());
return *this;
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_map& operator=(unordered_map&& x)
+ // C++17 support: BOOST_NOEXCEPT_IF(
+ // value_allocator_traits::is_always_equal::value &&
+ // is_nothrow_move_assignable_v<H> &&
+ // is_nothrow_move_assignable_v<P>)
{
- table_.move_assign(x.table_);
+ table_.move_assign(x.table_, boost::unordered::detail::true_type());
return *this;
}
#endif
@@ -182,14 +188,6 @@ template <class K, class T, class H, class P, class A> class unordered_map
return table_.node_alloc();
}
- // size and capacity
-
- bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; }
-
- size_type size() const BOOST_NOEXCEPT { return table_.size_; }
-
- size_type max_size() const BOOST_NOEXCEPT;
-
// iterators
iterator begin() BOOST_NOEXCEPT { return iterator(table_.begin()); }
@@ -210,311 +208,456 @@ template <class K, class T, class H, class P, class A> class unordered_map
const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); }
- // extract
+ // size and capacity
- node_type extract(const_iterator position)
- {
- return node_type(
- table_.extract_by_iterator(position), table_.node_alloc());
- }
+ bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; }
- node_type extract(const key_type& k)
- {
- return node_type(table_.extract_by_key(k), table_.node_alloc());
- }
+ size_type size() const BOOST_NOEXCEPT { return table_.size_; }
+
+ size_type max_size() const BOOST_NOEXCEPT;
// emplace
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
template <class... Args>
std::pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args)
{
- return table_.emplace(boost::forward<Args>(args)...);
+ return table_.emplace_unique(
+ table::extractor::extract(boost::forward<Args>(args)...),
+ boost::forward<Args>(args)...);
}
- template <class... Args>
- iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
+#else
+
+#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
+
+ // 0 argument emplace requires special treatment in case
+ // the container is instantiated with a value type that
+ // doesn't have a default constructor.
+
+ std::pair<iterator, bool> emplace(
+ boost::unordered::detail::empty_emplace =
+ boost::unordered::detail::empty_emplace(),
+ value_type v = value_type())
{
- return table_.emplace_hint(hint, boost::forward<Args>(args)...);
+ return this->emplace(boost::move(v));
}
- template <class... Args>
- std::pair<iterator, bool> try_emplace(
- key_type const& k, BOOST_FWD_REF(Args)... args)
+#endif
+
+ template <typename A0>
+ std::pair<iterator, bool> emplace(BOOST_FWD_REF(A0) a0)
{
- return table_.try_emplace_impl(k, boost::forward<Args>(args)...);
+ return table_.emplace_unique(
+ table::extractor::extract(boost::forward<A0>(a0)),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0)));
}
- template <class... Args>
- iterator try_emplace(
- const_iterator hint, key_type const& k, BOOST_FWD_REF(Args)... args)
+ template <typename A0, typename A1>
+ std::pair<iterator, bool> emplace(
+ BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{
- return table_.try_emplace_hint_impl(
- hint, k, boost::forward<Args>(args)...);
+ return table_.emplace_unique(
+ table::extractor::extract(
+ boost::forward<A0>(a0), boost::forward<A1>(a1)),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1)));
}
- template <class... Args>
- std::pair<iterator, bool> try_emplace(
- BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args)
+ template <typename A0, typename A1, typename A2>
+ std::pair<iterator, bool> emplace(
+ BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
- return table_.try_emplace_impl(
- boost::move(k), boost::forward<Args>(args)...);
+ return table_.emplace_unique(
+ table::extractor::extract(
+ boost::forward<A0>(a0), boost::forward<A1>(a1)),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1),
+ boost::forward<A2>(a2)));
}
+#endif
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
template <class... Args>
- iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k,
- BOOST_FWD_REF(Args)... args)
+ iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
{
- return table_.try_emplace_hint_impl(
- hint, boost::move(k), boost::forward<Args>(args)...);
+ return table_.emplace_hint_unique(hint,
+ table::extractor::extract(boost::forward<Args>(args)...),
+ boost::forward<Args>(args)...);
}
-#else
-#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
+#else
- // 0 argument emplace requires special treatment in case
- // the container is instantiated with a value type that
- // doesn't have a default constructor.
+#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
- std::pair<iterator, bool> emplace(
+ iterator emplace_hint(const_iterator hint,
boost::unordered::detail::empty_emplace =
boost::unordered::detail::empty_emplace(),
value_type v = value_type())
{
- return this->emplace(boost::move(v));
+ return this->emplace_hint(hint, boost::move(v));
}
- iterator emplace_hint(const_iterator hint,
- boost::unordered::detail::empty_emplace =
- boost::unordered::detail::empty_emplace(),
- value_type v = value_type())
+#endif
+
+ template <typename A0>
+ iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
{
- return this->emplace_hint(hint, boost::move(v));
+ return table_.emplace_hint_unique(hint,
+ table::extractor::extract(boost::forward<A0>(a0)),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0)));
+ }
+
+ template <typename A0, typename A1>
+ iterator emplace_hint(
+ const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
+ {
+ return table_.emplace_hint_unique(
+ hint, table::extractor::extract(
+ boost::forward<A0>(a0), boost::forward<A1>(a1)),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1)));
+ }
+
+ template <typename A0, typename A1, typename A2>
+ iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0,
+ BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
+ {
+ return table_.emplace_hint_unique(
+ hint, table::extractor::extract(
+ boost::forward<A0>(a0), boost::forward<A1>(a1)),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1),
+ boost::forward<A2>(a2)));
}
#endif
- template <typename Key>
- std::pair<iterator, bool> try_emplace(BOOST_FWD_REF(Key) k)
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+#define BOOST_UNORDERED_EMPLACE(z, n, _) \
+ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
+ std::pair<iterator, bool> emplace( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
+ { \
+ return table_.emplace_unique( \
+ table::extractor::extract( \
+ boost::forward<A0>(a0), boost::forward<A1>(a1)), \
+ boost::unordered::detail::create_emplace_args( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \
+ } \
+ \
+ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
+ iterator emplace_hint(const_iterator hint, \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
+ { \
+ return table_.emplace_hint_unique( \
+ hint, table::extractor::extract( \
+ boost::forward<A0>(a0), boost::forward<A1>(a1)), \
+ boost::unordered::detail::create_emplace_args( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \
+ }
+
+ BOOST_UNORDERED_EMPLACE(1, 4, _)
+ BOOST_UNORDERED_EMPLACE(1, 5, _)
+ BOOST_UNORDERED_EMPLACE(1, 6, _)
+ BOOST_UNORDERED_EMPLACE(1, 7, _)
+ BOOST_UNORDERED_EMPLACE(1, 8, _)
+ BOOST_UNORDERED_EMPLACE(1, 9, _)
+ BOOST_PP_REPEAT_FROM_TO(10, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT),
+ BOOST_UNORDERED_EMPLACE, _)
+
+#undef BOOST_UNORDERED_EMPLACE
+
+#endif
+
+ std::pair<iterator, bool> insert(value_type const& x)
{
- return table_.try_emplace_impl(boost::forward<Key>(k));
+ return this->emplace(x);
}
- template <typename Key>
- iterator try_emplace(const_iterator hint, BOOST_FWD_REF(Key) k)
+ std::pair<iterator, bool> insert(BOOST_RV_REF(value_type) x)
{
- return table_.try_emplace_hint_impl(hint, boost::forward<Key>(k));
+ return this->emplace(boost::move(x));
}
- template <typename A0>
- std::pair<iterator, bool> emplace(BOOST_FWD_REF(A0) a0)
+ template <class P2>
+ std::pair<iterator, bool> insert(BOOST_RV_REF(P2) obj,
+ typename boost::enable_if_c<
+ boost::is_constructible<value_type, BOOST_RV_REF(P2)>::value,
+ void*>::type = 0)
{
- return table_.emplace(boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0)));
+ return this->emplace(boost::forward<P2>(obj));
}
- template <typename A0>
- iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
+ iterator insert(const_iterator hint, value_type const& x)
{
- return table_.emplace_hint(
- hint, boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0)));
+ return this->emplace_hint(hint, x);
}
- template <typename A0>
- std::pair<iterator, bool> try_emplace(
- key_type const& k, BOOST_FWD_REF(A0) a0)
+ iterator insert(const_iterator hint, BOOST_RV_REF(value_type) x)
{
- return table_.try_emplace_impl(
- k, boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0)));
+ return this->emplace_hint(hint, boost::move(x));
}
- template <typename A0>
- iterator try_emplace(
- const_iterator hint, key_type const& k, BOOST_FWD_REF(A0) a0)
+ template <class P2>
+ iterator insert(const_iterator hint, BOOST_RV_REF(P2) obj,
+ typename boost::enable_if_c<
+ boost::is_constructible<value_type, BOOST_RV_REF(P2)>::value,
+ void*>::type = 0)
{
- return table_.try_emplace_hint_impl(
- hint, k, boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0)));
+ return this->emplace_hint(hint, boost::forward<P2>(obj));
}
- template <typename A0>
+ template <class InputIt> void insert(InputIt, InputIt);
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ void insert(std::initializer_list<value_type>);
+#endif
+
+ // extract
+
+ node_type extract(const_iterator position)
+ {
+ return node_type(
+ table_.extract_by_iterator_unique(position), table_.node_alloc());
+ }
+
+ node_type extract(const key_type& k)
+ {
+ return node_type(table_.extract_by_key(k), table_.node_alloc());
+ }
+
+ insert_return_type insert(BOOST_RV_REF(node_type) np)
+ {
+ insert_return_type result;
+ table_.move_insert_node_type_unique(np, result);
+ return boost::move(result);
+ }
+
+ iterator insert(const_iterator hint, BOOST_RV_REF(node_type) np)
+ {
+ return table_.move_insert_node_type_with_hint_unique(hint, np);
+ }
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \
+ (BOOST_COMP_GNUC && BOOST_COMP_GNUC < BOOST_VERSION_NUMBER(4, 6, 0))
+ private:
+ // Note: Use r-value node_type to insert.
+ insert_return_type insert(node_type&);
+ iterator insert(const_iterator, node_type& np);
+
+ public:
+#endif
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template <class... Args>
std::pair<iterator, bool> try_emplace(
- BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0)
+ key_type const& k, BOOST_FWD_REF(Args)... args)
{
- return table_.try_emplace_impl(
- boost::move(k), boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0)));
+ return table_.try_emplace_unique(k, boost::forward<Args>(args)...);
}
- template <typename A0>
+ template <class... Args>
+ std::pair<iterator, bool> try_emplace(
+ BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args)
+ {
+ return table_.try_emplace_unique(
+ boost::move(k), boost::forward<Args>(args)...);
+ }
+
+ template <class... Args>
iterator try_emplace(
- const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0)
+ const_iterator hint, key_type const& k, BOOST_FWD_REF(Args)... args)
{
- return table_.try_emplace_hint_impl(
- hint, boost::move(k), boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0)));
+ return table_.try_emplace_hint_unique(
+ hint, k, boost::forward<Args>(args)...);
}
- template <typename A0, typename A1>
- std::pair<iterator, bool> emplace(
- BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
+ template <class... Args>
+ iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k,
+ BOOST_FWD_REF(Args)... args)
{
- return table_.emplace(boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0), boost::forward<A1>(a1)));
+ return table_.try_emplace_hint_unique(
+ hint, boost::move(k), boost::forward<Args>(args)...);
}
- template <typename A0, typename A1>
- iterator emplace_hint(
- const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
+#else
+
+ // In order to make this a template, this handles both:
+ // try_emplace(key const&)
+ // try_emplace(key&&)
+
+ template <typename Key>
+ std::pair<iterator, bool> try_emplace(BOOST_FWD_REF(Key) k)
{
- return table_.emplace_hint(
- hint, boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0), boost::forward<A1>(a1)));
+ return table_.try_emplace_unique(boost::forward<Key>(k));
+ }
+
+ // In order to make this a template, this handles both:
+ // try_emplace(const_iterator hint, key const&)
+ // try_emplace(const_iterator hint, key&&)
+
+ template <typename Key>
+ iterator try_emplace(const_iterator hint, BOOST_FWD_REF(Key) k)
+ {
+ return table_.try_emplace_hint_unique(hint, boost::forward<Key>(k));
+ }
+
+ // try_emplace(key const&, Args&&...)
+
+ template <typename A0>
+ std::pair<iterator, bool> try_emplace(
+ key_type const& k, BOOST_FWD_REF(A0) a0)
+ {
+ return table_.try_emplace_unique(
+ k, boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0)));
}
template <typename A0, typename A1>
std::pair<iterator, bool> try_emplace(
key_type const& k, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{
- return table_.try_emplace_impl(
+ return table_.try_emplace_unique(
k, boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1)));
}
- template <typename A0, typename A1>
- iterator try_emplace(const_iterator hint, key_type const& k,
- BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
+ template <typename A0, typename A1, typename A2>
+ std::pair<iterator, bool> try_emplace(key_type const& k,
+ BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
- return table_.try_emplace_hint_impl(
- hint, k, boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0), boost::forward<A1>(a1)));
+ return table_.try_emplace_unique(
+ k, boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1),
+ boost::forward<A2>(a2)));
}
- template <typename A0, typename A1>
+ // try_emplace(key&&, Args&&...)
+
+ template <typename A0>
std::pair<iterator, bool> try_emplace(
- BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
+ BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0)
{
- return table_.try_emplace_impl(
- boost::move(k),
- boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0), boost::forward<A1>(a1)));
+ return table_.try_emplace_unique(
+ boost::move(k), boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0)));
}
template <typename A0, typename A1>
- iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k,
- BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
+ std::pair<iterator, bool> try_emplace(
+ BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{
- return table_.try_emplace_hint_impl(
- hint, boost::move(k),
+ return table_.try_emplace_unique(
+ boost::move(k),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1)));
}
template <typename A0, typename A1, typename A2>
- std::pair<iterator, bool> emplace(
+ std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k,
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
- return table_.emplace(boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0), boost::forward<A1>(a1),
- boost::forward<A2>(a2)));
+ return table_.try_emplace_unique(
+ boost::move(k), boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1),
+ boost::forward<A2>(a2)));
}
- template <typename A0, typename A1, typename A2>
- iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0,
- BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
+ // try_emplace(const_iterator hint, key const&, Args&&...)
+
+ template <typename A0>
+ iterator try_emplace(
+ const_iterator hint, key_type const& k, BOOST_FWD_REF(A0) a0)
{
- return table_.emplace_hint(
- hint, boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0), boost::forward<A1>(a1),
- boost::forward<A2>(a2)));
+ return table_.try_emplace_hint_unique(
+ hint, k, boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0)));
}
- template <typename A0, typename A1, typename A2>
- std::pair<iterator, bool> try_emplace(key_type const& k,
- BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
+ template <typename A0, typename A1>
+ iterator try_emplace(const_iterator hint, key_type const& k,
+ BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{
- return table_.try_emplace_impl(
- k, boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0), boost::forward<A1>(a1),
- boost::forward<A2>(a2)));
+ return table_.try_emplace_hint_unique(
+ hint, k, boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1)));
}
template <typename A0, typename A1, typename A2>
iterator try_emplace(const_iterator hint, key_type const& k,
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
- return table_
- .try_emplace_impl_(
- hint, k, boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0), boost::forward<A1>(a1),
- boost::forward<A2>(a2)))
- .first;
+ return table_.try_emplace_hint_unique(
+ hint, k, boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1),
+ boost::forward<A2>(a2)));
}
- template <typename A0, typename A1, typename A2>
- std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k,
- BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
+ // try_emplace(const_iterator hint, key&&, Args&&...)
+
+ template <typename A0>
+ iterator try_emplace(
+ const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0)
{
- return table_.try_emplace_impl(
- boost::move(k), boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0), boost::forward<A1>(a1),
- boost::forward<A2>(a2)));
+ return table_.try_emplace_hint_unique(
+ hint, boost::move(k), boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0)));
+ }
+
+ template <typename A0, typename A1>
+ iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k,
+ BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
+ {
+ return table_.try_emplace_hint_unique(
+ hint, boost::move(k),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1)));
}
template <typename A0, typename A1, typename A2>
iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k,
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
- return table_.try_emplace_hint_impl(
+ return table_.try_emplace_hint_unique(
hint, boost::move(k),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1),
boost::forward<A2>(a2)));
}
-#define BOOST_UNORDERED_EMPLACE(z, n, _) \
- template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
- std::pair<iterator, bool> emplace( \
- BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
- { \
- return table_.emplace(boost::unordered::detail::create_emplace_args( \
- BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \
- } \
- \
- template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
- iterator emplace_hint(const_iterator hint, \
- BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
- { \
- return table_.emplace_hint( \
- hint, boost::unordered::detail::create_emplace_args( \
- BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \
- } \
+#define BOOST_UNORDERED_TRY_EMPLACE(z, n, _) \
\
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
std::pair<iterator, bool> try_emplace( \
key_type const& k, BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \
- return table_.try_emplace_impl( \
+ return table_.try_emplace_unique( \
k, boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \
} \
\
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
- iterator try_emplace(const_iterator hint, key_type const& k, \
+ std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \
- return table_.try_emplace_hint_impl(hint, k, \
+ return table_.try_emplace_unique(boost::move(k), \
boost::unordered::detail::create_emplace_args(BOOST_PP_ENUM_##z( \
n, BOOST_UNORDERED_CALL_FORWARD, a))); \
} \
\
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
- std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k, \
+ iterator try_emplace(const_iterator hint, key_type const& k, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \
- return table_.try_emplace_impl(boost::move(k), \
+ return table_.try_emplace_hint_unique(hint, k, \
boost::unordered::detail::create_emplace_args(BOOST_PP_ENUM_##z( \
n, BOOST_UNORDERED_CALL_FORWARD, a))); \
} \
@@ -523,58 +666,44 @@ template <class K, class T, class H, class P, class A> class unordered_map
iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \
- return table_.try_emplace_hint_impl(hint, boost::move(k), \
+ return table_.try_emplace_hint_unique(hint, boost::move(k), \
boost::unordered::detail::create_emplace_args(BOOST_PP_ENUM_##z( \
n, BOOST_UNORDERED_CALL_FORWARD, a))); \
}
- BOOST_PP_REPEAT_FROM_TO(
- 4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EMPLACE, _)
+ BOOST_UNORDERED_TRY_EMPLACE(1, 4, _)
+ BOOST_UNORDERED_TRY_EMPLACE(1, 5, _)
+ BOOST_UNORDERED_TRY_EMPLACE(1, 6, _)
+ BOOST_UNORDERED_TRY_EMPLACE(1, 7, _)
+ BOOST_UNORDERED_TRY_EMPLACE(1, 8, _)
+ BOOST_UNORDERED_TRY_EMPLACE(1, 9, _)
+ BOOST_PP_REPEAT_FROM_TO(10, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT),
+ BOOST_UNORDERED_TRY_EMPLACE, _)
-#undef BOOST_UNORDERED_EMPLACE
+#undef BOOST_UNORDERED_TRY_EMPLACE
#endif
- std::pair<iterator, bool> insert(value_type const& x)
- {
- return this->emplace(x);
- }
-
- std::pair<iterator, bool> insert(BOOST_RV_REF(value_type) x)
- {
- return this->emplace(boost::move(x));
- }
-
- iterator insert(const_iterator hint, value_type const& x)
- {
- return this->emplace_hint(hint, x);
- }
-
- iterator insert(const_iterator hint, BOOST_RV_REF(value_type) x)
- {
- return this->emplace_hint(hint, boost::move(x));
- }
-
template <class M>
std::pair<iterator, bool> insert_or_assign(
key_type const& k, BOOST_FWD_REF(M) obj)
{
- return table_.insert_or_assign_impl(k, boost::forward<M>(obj));
+ return table_.insert_or_assign_unique(k, boost::forward<M>(obj));
}
template <class M>
- iterator insert_or_assign(
- const_iterator, key_type const& k, BOOST_FWD_REF(M) obj)
+ std::pair<iterator, bool> insert_or_assign(
+ BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
{
- return table_.insert_or_assign_impl(k, boost::forward<M>(obj)).first;
+ return table_.insert_or_assign_unique(
+ boost::move(k), boost::forward<M>(obj));
}
template <class M>
- std::pair<iterator, bool> insert_or_assign(
- BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
+ iterator insert_or_assign(
+ const_iterator, key_type const& k, BOOST_FWD_REF(M) obj)
{
- return table_.insert_or_assign_impl(
- boost::move(k), boost::forward<M>(obj));
+ return table_.insert_or_assign_unique(k, boost::forward<M>(obj)).first;
}
template <class M>
@@ -582,45 +711,25 @@ template <class K, class T, class H, class P, class A> class unordered_map
const_iterator, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
{
return table_
- .insert_or_assign_impl(boost::move(k), boost::forward<M>(obj))
+ .insert_or_assign_unique(boost::move(k), boost::forward<M>(obj))
.first;
}
- template <class InputIt> void insert(InputIt, InputIt);
-
-#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
- void insert(std::initializer_list<value_type>);
-#endif
-
- insert_return_type insert(BOOST_RV_REF(node_type) np)
- {
- insert_return_type result;
- table_.move_insert_node_type(np, result);
- return boost::move(result);
- }
-
- iterator insert(const_iterator hint, BOOST_RV_REF(node_type) np)
- {
- return table_.move_insert_node_type_with_hint(hint, np);
- }
-
-#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- private:
- // Note: Use r-value node_type to insert.
- insert_return_type insert(node_type&);
- iterator insert(const_iterator, node_type& np);
-
- public:
-#endif
-
+ iterator erase(iterator);
iterator erase(const_iterator);
size_type erase(const key_type&);
iterator erase(const_iterator, const_iterator);
+ BOOST_UNORDERED_DEPRECATED("Use erase instead")
void quick_erase(const_iterator it) { erase(it); }
+ BOOST_UNORDERED_DEPRECATED("Use erase instead")
void erase_return_void(const_iterator it) { erase(it); }
- void clear();
void swap(unordered_map&);
+ // C++17 support: BOOST_NOEXCEPT_IF(
+ // value_allocator_traits::is_always_equal::value &&
+ // is_nothrow_move_assignable_v<H> &&
+ // is_nothrow_move_assignable_v<P>)
+ void clear() BOOST_NOEXCEPT { table_.clear_impl(); }
template <typename H2, typename P2>
void merge(boost::unordered_map<K, T, H2, P2, A>& source);
@@ -630,7 +739,6 @@ template <class K, class T, class H, class P, class A> class unordered_map
void merge(boost::unordered_map<K, T, H2, P2, A>&& source);
#endif
-#if BOOST_UNORDERED_INTEROPERABLE_NODES
template <typename H2, typename P2>
void merge(boost::unordered_multimap<K, T, H2, P2, A>& source);
@@ -638,17 +746,12 @@ template <class K, class T, class H, class P, class A> class unordered_map
template <typename H2, typename P2>
void merge(boost::unordered_multimap<K, T, H2, P2, A>&& source);
#endif
-#endif
// observers
hasher hash_function() const;
key_equal key_eq() const;
- mapped_type& operator[](const key_type&);
- mapped_type& at(const key_type&);
- mapped_type const& at(const key_type&) const;
-
// lookup
iterator find(const key_type&);
@@ -670,6 +773,11 @@ template <class K, class T, class H, class P, class A> class unordered_map
std::pair<const_iterator, const_iterator> equal_range(
const key_type&) const;
+ mapped_type& operator[](const key_type&);
+ mapped_type& operator[](BOOST_RV_REF(key_type));
+ mapped_type& at(const key_type&);
+ mapped_type const& at(const key_type&) const;
+
// bucket interface
size_type bucket_count() const BOOST_NOEXCEPT
@@ -715,9 +823,8 @@ template <class K, class T, class H, class P, class A> class unordered_map
// hash policy
- float max_load_factor() const BOOST_NOEXCEPT { return table_.mlf_; }
-
float load_factor() const BOOST_NOEXCEPT;
+ float max_load_factor() const BOOST_NOEXCEPT { return table_.mlf_; }
void max_load_factor(float) BOOST_NOEXCEPT;
void rehash(size_type);
void reserve(size_type);
@@ -740,16 +847,18 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
public:
typedef K key_type;
- typedef std::pair<const K, T> value_type;
typedef T mapped_type;
+ typedef std::pair<const K, T> value_type;
typedef H hasher;
typedef P key_equal;
typedef A allocator_type;
private:
- typedef boost::unordered::detail::multimap<A, K, T, H, P> types;
+ typedef boost::unordered::detail::map<A, K, T, H, P> types;
typedef typename types::value_allocator_traits value_allocator_traits;
typedef typename types::table table;
+ typedef typename table::node_pointer node_pointer;
+ typedef typename table::link_pointer link_pointer;
public:
typedef typename value_allocator_traits::pointer pointer;
@@ -761,10 +870,10 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
- typedef typename table::cl_iterator const_local_iterator;
- typedef typename table::l_iterator local_iterator;
- typedef typename table::c_iterator const_iterator;
typedef typename table::iterator iterator;
+ typedef typename table::c_iterator const_iterator;
+ typedef typename table::l_iterator local_iterator;
+ typedef typename table::cl_iterator const_local_iterator;
typedef typename types::node_type node_type;
private:
@@ -779,60 +888,55 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
const key_equal& = key_equal(),
const allocator_type& = allocator_type());
- explicit unordered_multimap(size_type, const allocator_type&);
-
- explicit unordered_multimap(
- size_type, const hasher&, const allocator_type&);
-
- explicit unordered_multimap(allocator_type const&);
-
- template <class InputIt> unordered_multimap(InputIt, InputIt);
-
template <class InputIt>
- unordered_multimap(InputIt, InputIt, size_type, const hasher& = hasher(),
- const key_equal& = key_equal());
-
- template <class InputIt>
- unordered_multimap(InputIt, InputIt, size_type, const hasher&,
- const key_equal&, const allocator_type&);
-
- template <class InputIt>
- unordered_multimap(
- InputIt, InputIt, size_type, const hasher&, const allocator_type&);
-
- template <class InputIt>
- unordered_multimap(InputIt, InputIt, size_type, const allocator_type&);
-
- // copy/move constructors
+ unordered_multimap(InputIt, InputIt,
+ size_type = boost::unordered::detail::default_bucket_count,
+ const hasher& = hasher(), const key_equal& = key_equal(),
+ const allocator_type& = allocator_type());
unordered_multimap(unordered_multimap const&);
- unordered_multimap(unordered_multimap const&, allocator_type const&);
- unordered_multimap(BOOST_RV_REF(unordered_multimap), allocator_type const&);
-
-#if defined(BOOST_UNORDERED_USE_MOVE)
+#if defined(BOOST_UNORDERED_USE_MOVE) || \
+ !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multimap(BOOST_RV_REF(unordered_multimap) other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
- }
-#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- unordered_multimap(unordered_multimap&& other)
- BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
- : table_(other.table_, boost::unordered::detail::move_tag())
- {
+ // The move is done in table_
}
#endif
+ explicit unordered_multimap(allocator_type const&);
+
+ unordered_multimap(unordered_multimap const&, allocator_type const&);
+
+ unordered_multimap(BOOST_RV_REF(unordered_multimap), allocator_type const&);
+
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_multimap(std::initializer_list<value_type>,
size_type = boost::unordered::detail::default_bucket_count,
const hasher& = hasher(), const key_equal& l = key_equal(),
const allocator_type& = allocator_type());
- unordered_multimap(std::initializer_list<value_type>, size_type,
- const hasher&, const allocator_type&);
+#endif
+
+ explicit unordered_multimap(size_type, const allocator_type&);
+
+ explicit unordered_multimap(
+ size_type, const hasher&, const allocator_type&);
+
+ template <class InputIt>
+ unordered_multimap(InputIt, InputIt, size_type, const allocator_type&);
+
+ template <class InputIt>
+ unordered_multimap(
+ InputIt, InputIt, size_type, const hasher&, const allocator_type&);
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_multimap(
std::initializer_list<value_type>, size_type, const allocator_type&);
+
+ unordered_multimap(std::initializer_list<value_type>, size_type,
+ const hasher&, const allocator_type&);
#endif
// Destructor
@@ -844,26 +948,34 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_multimap& operator=(BOOST_COPY_ASSIGN_REF(unordered_multimap) x)
{
- table_.assign(x.table_);
+ table_.assign(x.table_, boost::unordered::detail::false_type());
return *this;
}
unordered_multimap& operator=(BOOST_RV_REF(unordered_multimap) x)
+ // C++17 support: BOOST_NOEXCEPT_IF(
+ // value_allocator_traits::is_always_equal::value &&
+ // is_nothrow_move_assignable_v<H> &&
+ // is_nothrow_move_assignable_v<P>)
{
- table_.move_assign(x.table_);
+ table_.move_assign(x.table_, boost::unordered::detail::false_type());
return *this;
}
#else
unordered_multimap& operator=(unordered_multimap const& x)
{
- table_.assign(x.table_);
+ table_.assign(x.table_, boost::unordered::detail::false_type());
return *this;
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multimap& operator=(unordered_multimap&& x)
+ // C++17 support: BOOST_NOEXCEPT_IF(
+ // value_allocator_traits::is_always_equal::value &&
+ // is_nothrow_move_assignable_v<H> &&
+ // is_nothrow_move_assignable_v<P>)
{
- table_.move_assign(x.table_);
+ table_.move_assign(x.table_, boost::unordered::detail::false_type());
return *this;
}
#endif
@@ -878,14 +990,6 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
return table_.node_alloc();
}
- // size and capacity
-
- bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; }
-
- size_type size() const BOOST_NOEXCEPT { return table_.size_; }
-
- size_type max_size() const BOOST_NOEXCEPT;
-
// iterators
iterator begin() BOOST_NOEXCEPT { return iterator(table_.begin()); }
@@ -906,35 +1010,28 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); }
- // extract
+ // size and capacity
- node_type extract(const_iterator position)
- {
- return node_type(
- table_.extract_by_iterator(position), table_.node_alloc());
- }
+ bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; }
- node_type extract(const key_type& k)
- {
- return node_type(table_.extract_by_key(k), table_.node_alloc());
- }
+ size_type size() const BOOST_NOEXCEPT { return table_.size_; }
+
+ size_type max_size() const BOOST_NOEXCEPT;
// emplace
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
template <class... Args> iterator emplace(BOOST_FWD_REF(Args)... args)
{
- return table_.emplace(boost::forward<Args>(args)...);
+ return iterator(table_.emplace_equiv(
+ boost::unordered::detail::func::construct_node_from_args(
+ table_.node_alloc(), boost::forward<Args>(args)...)));
}
- template <class... Args>
- iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
- {
- return table_.emplace_hint(hint, boost::forward<Args>(args)...);
- }
#else
-#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
+#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
// 0 argument emplace requires special treatment in case
// the container is instantiated with a value type that
@@ -947,6 +1044,55 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
return this->emplace(boost::move(v));
}
+#endif
+
+ template <typename A0> iterator emplace(BOOST_FWD_REF(A0) a0)
+ {
+ return iterator(table_.emplace_equiv(
+ boost::unordered::detail::func::construct_node_from_args(
+ table_.node_alloc(),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0)))));
+ }
+
+ template <typename A0, typename A1>
+ iterator emplace(BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
+ {
+ return iterator(table_.emplace_equiv(
+ boost::unordered::detail::func::construct_node_from_args(
+ table_.node_alloc(),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1)))));
+ }
+
+ template <typename A0, typename A1, typename A2>
+ iterator emplace(
+ BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
+ {
+ return iterator(table_.emplace_equiv(
+ boost::unordered::detail::func::construct_node_from_args(
+ table_.node_alloc(),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1),
+ boost::forward<A2>(a2)))));
+ }
+
+#endif
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template <class... Args>
+ iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
+ {
+ return iterator(table_.emplace_hint_equiv(
+ hint, boost::unordered::detail::func::construct_node_from_args(
+ table_.node_alloc(), boost::forward<Args>(args)...)));
+ }
+
+#else
+
+#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
+
iterator emplace_hint(const_iterator hint,
boost::unordered::detail::empty_emplace =
boost::unordered::detail::empty_emplace(),
@@ -957,74 +1103,74 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
#endif
- template <typename A0> iterator emplace(BOOST_FWD_REF(A0) a0)
- {
- return table_.emplace(boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0)));
- }
-
template <typename A0>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
{
- return table_.emplace_hint(
- hint, boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0)));
- }
-
- template <typename A0, typename A1>
- iterator emplace(BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
- {
- return table_.emplace(boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0), boost::forward<A1>(a1)));
+ return iterator(table_.emplace_hint_equiv(
+ hint, boost::unordered::detail::func::construct_node_from_args(
+ table_.node_alloc(),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0)))));
}
template <typename A0, typename A1>
iterator emplace_hint(
const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{
- return table_.emplace_hint(
- hint, boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0), boost::forward<A1>(a1)));
- }
-
- template <typename A0, typename A1, typename A2>
- iterator emplace(
- BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
- {
- return table_.emplace(boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0), boost::forward<A1>(a1),
- boost::forward<A2>(a2)));
+ return iterator(table_.emplace_hint_equiv(
+ hint, boost::unordered::detail::func::construct_node_from_args(
+ table_.node_alloc(),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1)))));
}
template <typename A0, typename A1, typename A2>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
- return table_.emplace_hint(
- hint, boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0), boost::forward<A1>(a1),
- boost::forward<A2>(a2)));
+ return iterator(table_.emplace_hint_equiv(
+ hint, boost::unordered::detail::func::construct_node_from_args(
+ table_.node_alloc(),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1),
+ boost::forward<A2>(a2)))));
}
+#endif
+
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
iterator emplace(BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \
- return table_.emplace(boost::unordered::detail::create_emplace_args( \
- BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \
+ return iterator(table_.emplace_equiv( \
+ boost::unordered::detail::func::construct_node_from_args( \
+ table_.node_alloc(), \
+ boost::unordered::detail::create_emplace_args( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))))); \
} \
\
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
iterator emplace_hint(const_iterator hint, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \
- return table_.emplace_hint( \
- hint, boost::unordered::detail::create_emplace_args( \
- BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \
- }
-
- BOOST_PP_REPEAT_FROM_TO(
- 4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EMPLACE, _)
+ return iterator(table_.emplace_hint_equiv( \
+ hint, \
+ boost::unordered::detail::func::construct_node_from_args( \
+ table_.node_alloc(), \
+ boost::unordered::detail::create_emplace_args( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))))); \
+ }
+
+ BOOST_UNORDERED_EMPLACE(1, 4, _)
+ BOOST_UNORDERED_EMPLACE(1, 5, _)
+ BOOST_UNORDERED_EMPLACE(1, 6, _)
+ BOOST_UNORDERED_EMPLACE(1, 7, _)
+ BOOST_UNORDERED_EMPLACE(1, 8, _)
+ BOOST_UNORDERED_EMPLACE(1, 9, _)
+ BOOST_PP_REPEAT_FROM_TO(10, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT),
+ BOOST_UNORDERED_EMPLACE, _)
#undef BOOST_UNORDERED_EMPLACE
@@ -1037,6 +1183,15 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
return this->emplace(boost::move(x));
}
+ template <class P2>
+ iterator insert(BOOST_RV_REF(P2) obj,
+ typename boost::enable_if_c<
+ boost::is_constructible<value_type, BOOST_RV_REF(P2)>::value,
+ void*>::type = 0)
+ {
+ return this->emplace(boost::forward<P2>(obj));
+ }
+
iterator insert(const_iterator hint, value_type const& x)
{
return this->emplace_hint(hint, x);
@@ -1047,23 +1202,46 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
return this->emplace_hint(hint, boost::move(x));
}
+ template <class P2>
+ iterator insert(const_iterator hint, BOOST_RV_REF(P2) obj,
+ typename boost::enable_if_c<
+ boost::is_constructible<value_type, BOOST_RV_REF(P2)>::value,
+ void*>::type = 0)
+ {
+ return this->emplace_hint(hint, boost::forward<P2>(obj));
+ }
+
template <class InputIt> void insert(InputIt, InputIt);
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
void insert(std::initializer_list<value_type>);
#endif
+ // extract
+
+ node_type extract(const_iterator position)
+ {
+ return node_type(
+ table_.extract_by_iterator_equiv(position), table_.node_alloc());
+ }
+
+ node_type extract(const key_type& k)
+ {
+ return node_type(table_.extract_by_key(k), table_.node_alloc());
+ }
+
iterator insert(BOOST_RV_REF(node_type) np)
{
- return table_.move_insert_node_type(np);
+ return table_.move_insert_node_type_equiv(np);
}
iterator insert(const_iterator hint, BOOST_RV_REF(node_type) np)
{
- return table_.move_insert_node_type_with_hint(hint, np);
+ return table_.move_insert_node_type_with_hint_equiv(hint, np);
}
-#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \
+ (BOOST_COMP_GNUC && BOOST_COMP_GNUC < BOOST_VERSION_NUMBER(4, 6, 0))
private:
// Note: Use r-value node_type to insert.
iterator insert(node_type&);
@@ -1072,14 +1250,21 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
public:
#endif
+ iterator erase(iterator);
iterator erase(const_iterator);
size_type erase(const key_type&);
iterator erase(const_iterator, const_iterator);
+ BOOST_UNORDERED_DEPRECATED("Use erase instead")
void quick_erase(const_iterator it) { erase(it); }
+ BOOST_UNORDERED_DEPRECATED("Use erase instead")
void erase_return_void(const_iterator it) { erase(it); }
- void clear();
void swap(unordered_multimap&);
+ // C++17 support: BOOST_NOEXCEPT_IF(
+ // value_allocator_traits::is_always_equal::value &&
+ // is_nothrow_move_assignable_v<H> &&
+ // is_nothrow_move_assignable_v<P>)
+ void clear() BOOST_NOEXCEPT { table_.clear_impl(); }
template <typename H2, typename P2>
void merge(boost::unordered_multimap<K, T, H2, P2, A>& source);
@@ -1089,7 +1274,6 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
void merge(boost::unordered_multimap<K, T, H2, P2, A>&& source);
#endif
-#if BOOST_UNORDERED_INTEROPERABLE_NODES
template <typename H2, typename P2>
void merge(boost::unordered_map<K, T, H2, P2, A>& source);
@@ -1097,7 +1281,6 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
template <typename H2, typename P2>
void merge(boost::unordered_map<K, T, H2, P2, A>&& source);
#endif
-#endif
// observers
@@ -1170,9 +1353,8 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
// hash policy
- float max_load_factor() const BOOST_NOEXCEPT { return table_.mlf_; }
-
float load_factor() const BOOST_NOEXCEPT;
+ float max_load_factor() const BOOST_NOEXCEPT { return table_.mlf_; }
void max_load_factor(float) BOOST_NOEXCEPT;
void rehash(size_type);
void reserve(size_type);
@@ -1202,17 +1384,24 @@ unordered_map<K, T, H, P, A>::unordered_map(size_type n, const hasher& hf,
}
template <class K, class T, class H, class P, class A>
-unordered_map<K, T, H, P, A>::unordered_map(
- size_type n, const allocator_type& a)
- : table_(n, hasher(), key_equal(), a)
+template <class InputIt>
+unordered_map<K, T, H, P, A>::unordered_map(InputIt f, InputIt l, size_type n,
+ const hasher& hf, const key_equal& eql, const allocator_type& a)
+ : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
{
+ this->insert(f, l);
}
template <class K, class T, class H, class P, class A>
-unordered_map<K, T, H, P, A>::unordered_map(
- size_type n, const hasher& hf, const allocator_type& a)
- : table_(n, hf, key_equal(), a)
+unordered_map<K, T, H, P, A>::unordered_map(unordered_map const& other)
+ : table_(other.table_,
+ unordered_map::value_allocator_traits::
+ select_on_container_copy_construction(other.get_allocator()))
{
+ if (other.table_.size_) {
+ table_.copy_buckets(
+ other.table_, boost::unordered::detail::true_type());
+ }
}
template <class K, class T, class H, class P, class A>
@@ -1227,44 +1416,52 @@ unordered_map<K, T, H, P, A>::unordered_map(
unordered_map const& other, allocator_type const& a)
: table_(other.table_, a)
{
+ if (other.table_.size_) {
+ table_.copy_buckets(
+ other.table_, boost::unordered::detail::true_type());
+ }
}
template <class K, class T, class H, class P, class A>
-template <class InputIt>
-unordered_map<K, T, H, P, A>::unordered_map(InputIt f, InputIt l)
- : table_(boost::unordered::detail::initial_size(f, l), hasher(),
- key_equal(), allocator_type())
+unordered_map<K, T, H, P, A>::unordered_map(
+ BOOST_RV_REF(unordered_map) other, allocator_type const& a)
+ : table_(other.table_, a, boost::unordered::detail::move_tag())
{
- table_.insert_range(f, l);
+ if (table_.node_alloc() == other.table_.node_alloc()) {
+ table_.move_buckets_from(other.table_);
+ } else if (other.table_.size_) {
+ // TODO: Could pick new bucket size?
+ table_.move_buckets(other.table_);
+ }
}
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+
template <class K, class T, class H, class P, class A>
-template <class InputIt>
unordered_map<K, T, H, P, A>::unordered_map(
- InputIt f, InputIt l, size_type n, const hasher& hf, const key_equal& eql)
- : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql,
- allocator_type())
+ std::initializer_list<value_type> list, size_type n, const hasher& hf,
+ const key_equal& eql, const allocator_type& a)
+ : table_(
+ boost::unordered::detail::initial_size(list.begin(), list.end(), n),
+ hf, eql, a)
{
- table_.insert_range(f, l);
+ this->insert(list.begin(), list.end());
}
+#endif
+
template <class K, class T, class H, class P, class A>
-template <class InputIt>
-unordered_map<K, T, H, P, A>::unordered_map(InputIt f, InputIt l, size_type n,
- const hasher& hf, const key_equal& eql, const allocator_type& a)
- : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
+unordered_map<K, T, H, P, A>::unordered_map(
+ size_type n, const allocator_type& a)
+ : table_(n, hasher(), key_equal(), a)
{
- table_.insert_range(f, l);
}
template <class K, class T, class H, class P, class A>
-template <class InputIt>
-unordered_map<K, T, H, P, A>::unordered_map(InputIt f, InputIt l, size_type n,
- const hasher& hf, const allocator_type& a)
- : table_(
- boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
+unordered_map<K, T, H, P, A>::unordered_map(
+ size_type n, const hasher& hf, const allocator_type& a)
+ : table_(n, hf, key_equal(), a)
{
- table_.insert_range(f, l);
}
template <class K, class T, class H, class P, class A>
@@ -1274,38 +1471,30 @@ unordered_map<K, T, H, P, A>::unordered_map(
: table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
key_equal(), a)
{
- table_.insert_range(f, l);
-}
-
-template <class K, class T, class H, class P, class A>
-unordered_map<K, T, H, P, A>::~unordered_map() BOOST_NOEXCEPT
-{
+ this->insert(f, l);
}
template <class K, class T, class H, class P, class A>
-unordered_map<K, T, H, P, A>::unordered_map(unordered_map const& other)
- : table_(other.table_)
-{
-}
-
-template <class K, class T, class H, class P, class A>
-unordered_map<K, T, H, P, A>::unordered_map(
- BOOST_RV_REF(unordered_map) other, allocator_type const& a)
- : table_(other.table_, a, boost::unordered::detail::move_tag())
+template <class InputIt>
+unordered_map<K, T, H, P, A>::unordered_map(InputIt f, InputIt l, size_type n,
+ const hasher& hf, const allocator_type& a)
+ : table_(
+ boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
{
+ this->insert(f, l);
}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class K, class T, class H, class P, class A>
unordered_map<K, T, H, P, A>::unordered_map(
- std::initializer_list<value_type> list, size_type n, const hasher& hf,
- const key_equal& eql, const allocator_type& a)
+ std::initializer_list<value_type> list, size_type n,
+ const allocator_type& a)
: table_(
boost::unordered::detail::initial_size(list.begin(), list.end(), n),
- hf, eql, a)
+ hasher(), key_equal(), a)
{
- table_.insert_range(list.begin(), list.end());
+ this->insert(list.begin(), list.end());
}
template <class K, class T, class H, class P, class A>
@@ -1316,26 +1505,24 @@ unordered_map<K, T, H, P, A>::unordered_map(
boost::unordered::detail::initial_size(list.begin(), list.end(), n),
hf, key_equal(), a)
{
- table_.insert_range(list.begin(), list.end());
+ this->insert(list.begin(), list.end());
}
+#endif
+
template <class K, class T, class H, class P, class A>
-unordered_map<K, T, H, P, A>::unordered_map(
- std::initializer_list<value_type> list, size_type n,
- const allocator_type& a)
- : table_(
- boost::unordered::detail::initial_size(list.begin(), list.end(), n),
- hasher(), key_equal(), a)
+unordered_map<K, T, H, P, A>::~unordered_map() BOOST_NOEXCEPT
{
- table_.insert_range(list.begin(), list.end());
}
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+
template <class K, class T, class H, class P, class A>
unordered_map<K, T, H, P, A>& unordered_map<K, T, H, P, A>::operator=(
std::initializer_list<value_type> list)
{
- table_.clear();
- table_.insert_range(list.begin(), list.end());
+ this->clear();
+ this->insert(list.begin(), list.end());
return *this;
}
@@ -1346,7 +1533,13 @@ unordered_map<K, T, H, P, A>& unordered_map<K, T, H, P, A>::operator=(
template <class K, class T, class H, class P, class A>
std::size_t unordered_map<K, T, H, P, A>::max_size() const BOOST_NOEXCEPT
{
- return table_.max_size();
+ using namespace std;
+
+ // size <= mlf_ * count
+ return boost::unordered::detail::double_to_size(
+ ceil(static_cast<double>(table_.mlf_) *
+ static_cast<double>(table_.max_bucket_count()))) -
+ 1;
}
// modifiers
@@ -1355,7 +1548,10 @@ template <class K, class T, class H, class P, class A>
template <class InputIt>
void unordered_map<K, T, H, P, A>::insert(InputIt first, InputIt last)
{
- table_.insert_range(first, last);
+ if (first != last) {
+ table_.insert_range_unique(
+ table::extractor::extract(*first), first, last);
+ }
}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@@ -1363,39 +1559,56 @@ template <class K, class T, class H, class P, class A>
void unordered_map<K, T, H, P, A>::insert(
std::initializer_list<value_type> list)
{
- table_.insert_range(list.begin(), list.end());
+ this->insert(list.begin(), list.end());
}
#endif
template <class K, class T, class H, class P, class A>
typename unordered_map<K, T, H, P, A>::iterator
+unordered_map<K, T, H, P, A>::erase(iterator position)
+{
+ node_pointer node = table::get_node(position);
+ BOOST_ASSERT(node);
+ node_pointer next = table::next_node(node);
+ table_.erase_nodes_unique(node, next);
+ return iterator(next);
+}
+
+template <class K, class T, class H, class P, class A>
+typename unordered_map<K, T, H, P, A>::iterator
unordered_map<K, T, H, P, A>::erase(const_iterator position)
{
- return table_.erase(position);
+ node_pointer node = table::get_node(position);
+ BOOST_ASSERT(node);
+ node_pointer next = table::next_node(node);
+ table_.erase_nodes_unique(node, next);
+ return iterator(next);
}
template <class K, class T, class H, class P, class A>
typename unordered_map<K, T, H, P, A>::size_type
unordered_map<K, T, H, P, A>::erase(const key_type& k)
{
- return table_.erase_key(k);
+ return table_.erase_key_unique(k);
}
template <class K, class T, class H, class P, class A>
typename unordered_map<K, T, H, P, A>::iterator
unordered_map<K, T, H, P, A>::erase(const_iterator first, const_iterator last)
{
- return table_.erase_range(first, last);
-}
-
-template <class K, class T, class H, class P, class A>
-void unordered_map<K, T, H, P, A>::clear()
-{
- table_.clear();
+ node_pointer last_node = table::get_node(last);
+ if (first == last)
+ return iterator(last_node);
+ table_.erase_nodes_unique(table::get_node(first), last_node);
+ return iterator(last_node);
}
template <class K, class T, class H, class P, class A>
void unordered_map<K, T, H, P, A>::swap(unordered_map& other)
+// C++17 support: BOOST_NOEXCEPT_IF(
+// value_allocator_traits::is_always_equal::value &&
+// is_nothrow_move_assignable_v<H> &&
+// is_nothrow_move_assignable_v<P>)
{
table_.swap(other.table_);
}
@@ -1405,7 +1618,7 @@ template <typename H2, typename P2>
void unordered_map<K, T, H, P, A>::merge(
boost::unordered_map<K, T, H2, P2, A>& source)
{
- table_.merge_impl(source.table_);
+ table_.merge_unique(source.table_);
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
@@ -1414,17 +1627,16 @@ template <typename H2, typename P2>
void unordered_map<K, T, H, P, A>::merge(
boost::unordered_map<K, T, H2, P2, A>&& source)
{
- table_.merge_impl(source.table_);
+ table_.merge_unique(source.table_);
}
#endif
-#if BOOST_UNORDERED_INTEROPERABLE_NODES
template <class K, class T, class H, class P, class A>
template <typename H2, typename P2>
void unordered_map<K, T, H, P, A>::merge(
boost::unordered_multimap<K, T, H2, P2, A>& source)
{
- table_.merge_impl(source.table_);
+ table_.merge_unique(source.table_);
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
@@ -1433,10 +1645,9 @@ template <typename H2, typename P2>
void unordered_map<K, T, H, P, A>::merge(
boost::unordered_multimap<K, T, H2, P2, A>&& source)
{
- table_.merge_impl(source.table_);
+ table_.merge_unique(source.table_);
}
#endif
-#endif
// observers
@@ -1454,27 +1665,6 @@ unordered_map<K, T, H, P, A>::key_eq() const
return table_.key_eq();
}
-template <class K, class T, class H, class P, class A>
-typename unordered_map<K, T, H, P, A>::mapped_type&
- unordered_map<K, T, H, P, A>::operator[](const key_type& k)
-{
- return table_.try_emplace_impl(k).first->second;
-}
-
-template <class K, class T, class H, class P, class A>
-typename unordered_map<K, T, H, P, A>::mapped_type&
-unordered_map<K, T, H, P, A>::at(const key_type& k)
-{
- return table_.at(k).second;
-}
-
-template <class K, class T, class H, class P, class A>
-typename unordered_map<K, T, H, P, A>::mapped_type const&
-unordered_map<K, T, H, P, A>::at(const key_type& k) const
-{
- return table_.at(k).second;
-}
-
// lookup
template <class K, class T, class H, class P, class A>
@@ -1497,7 +1687,8 @@ typename unordered_map<K, T, H, P, A>::iterator
unordered_map<K, T, H, P, A>::find(CompatibleKey const& k,
CompatibleHash const& hash, CompatiblePredicate const& eq)
{
- return iterator(table_.generic_find_node(k, hash, eq));
+ return iterator(
+ table_.find_node_impl(table::policy::apply_hash(hash, k), k, eq));
}
template <class K, class T, class H, class P, class A>
@@ -1506,14 +1697,15 @@ typename unordered_map<K, T, H, P, A>::const_iterator
unordered_map<K, T, H, P, A>::find(CompatibleKey const& k,
CompatibleHash const& hash, CompatiblePredicate const& eq) const
{
- return const_iterator(table_.generic_find_node(k, hash, eq));
+ return const_iterator(
+ table_.find_node_impl(table::policy::apply_hash(hash, k), k, eq));
}
template <class K, class T, class H, class P, class A>
typename unordered_map<K, T, H, P, A>::size_type
unordered_map<K, T, H, P, A>::count(const key_type& k) const
{
- return table_.count(k);
+ return table_.find_node(k) ? 1 : 0;
}
template <class K, class T, class H, class P, class A>
@@ -1521,7 +1713,8 @@ std::pair<typename unordered_map<K, T, H, P, A>::iterator,
typename unordered_map<K, T, H, P, A>::iterator>
unordered_map<K, T, H, P, A>::equal_range(const key_type& k)
{
- return table_.equal_range(k);
+ node_pointer n = table_.find_node(k);
+ return std::make_pair(iterator(n), iterator(n ? table::next_node(n) : n));
}
template <class K, class T, class H, class P, class A>
@@ -1529,7 +1722,51 @@ std::pair<typename unordered_map<K, T, H, P, A>::const_iterator,
typename unordered_map<K, T, H, P, A>::const_iterator>
unordered_map<K, T, H, P, A>::equal_range(const key_type& k) const
{
- return table_.equal_range(k);
+ node_pointer n = table_.find_node(k);
+ return std::make_pair(
+ const_iterator(n), const_iterator(n ? table::next_node(n) : n));
+}
+
+template <class K, class T, class H, class P, class A>
+typename unordered_map<K, T, H, P, A>::mapped_type&
+ unordered_map<K, T, H, P, A>::operator[](const key_type& k)
+{
+ return table_.try_emplace_unique(k).first->second;
+}
+
+template <class K, class T, class H, class P, class A>
+typename unordered_map<K, T, H, P, A>::mapped_type&
+ unordered_map<K, T, H, P, A>::operator[](BOOST_RV_REF(key_type) k)
+{
+ return table_.try_emplace_unique(boost::move(k)).first->second;
+}
+
+template <class K, class T, class H, class P, class A>
+typename unordered_map<K, T, H, P, A>::mapped_type&
+unordered_map<K, T, H, P, A>::at(const key_type& k)
+{
+ if (table_.size_) {
+ node_pointer n = table_.find_node(k);
+ if (n)
+ return n->value().second;
+ }
+
+ boost::throw_exception(
+ std::out_of_range("Unable to find key in unordered_map."));
+}
+
+template <class K, class T, class H, class P, class A>
+typename unordered_map<K, T, H, P, A>::mapped_type const&
+unordered_map<K, T, H, P, A>::at(const key_type& k) const
+{
+ if (table_.size_) {
+ node_pointer n = table_.find_node(k);
+ if (n)
+ return n->value().second;
+ }
+
+ boost::throw_exception(
+ std::out_of_range("Unable to find key in unordered_map."));
}
template <class K, class T, class H, class P, class A>
@@ -1544,7 +1781,9 @@ unordered_map<K, T, H, P, A>::bucket_size(size_type n) const
template <class K, class T, class H, class P, class A>
float unordered_map<K, T, H, P, A>::load_factor() const BOOST_NOEXCEPT
{
- return table_.load_factor();
+ BOOST_ASSERT(table_.bucket_count_ != 0);
+ return static_cast<float>(table_.size_) /
+ static_cast<float>(table_.bucket_count_);
}
template <class K, class T, class H, class P, class A>
@@ -1562,7 +1801,8 @@ void unordered_map<K, T, H, P, A>::rehash(size_type n)
template <class K, class T, class H, class P, class A>
void unordered_map<K, T, H, P, A>::reserve(size_type n)
{
- table_.reserve(n);
+ table_.rehash(static_cast<std::size_t>(
+ std::ceil(static_cast<double>(n) / table_.mlf_)));
}
template <class K, class T, class H, class P, class A>
@@ -1575,7 +1815,7 @@ inline bool operator==(unordered_map<K, T, H, P, A> const& m1,
unordered_map<K, T, H, P, A> x;
};
#endif
- return m1.table_.equals(m2.table_);
+ return m1.table_.equals_unique(m2.table_);
}
template <class K, class T, class H, class P, class A>
@@ -1588,12 +1828,13 @@ inline bool operator!=(unordered_map<K, T, H, P, A> const& m1,
unordered_map<K, T, H, P, A> x;
};
#endif
- return !m1.table_.equals(m2.table_);
+ return !m1.table_.equals_unique(m2.table_);
}
template <class K, class T, class H, class P, class A>
inline void swap(
unordered_map<K, T, H, P, A>& m1, unordered_map<K, T, H, P, A>& m2)
+ BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)))
{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy
@@ -1621,17 +1862,26 @@ unordered_multimap<K, T, H, P, A>::unordered_multimap(size_type n,
}
template <class K, class T, class H, class P, class A>
-unordered_multimap<K, T, H, P, A>::unordered_multimap(
- size_type n, const allocator_type& a)
- : table_(n, hasher(), key_equal(), a)
+template <class InputIt>
+unordered_multimap<K, T, H, P, A>::unordered_multimap(InputIt f, InputIt l,
+ size_type n, const hasher& hf, const key_equal& eql,
+ const allocator_type& a)
+ : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
{
+ this->insert(f, l);
}
template <class K, class T, class H, class P, class A>
unordered_multimap<K, T, H, P, A>::unordered_multimap(
- size_type n, const hasher& hf, const allocator_type& a)
- : table_(n, hf, key_equal(), a)
+ unordered_multimap const& other)
+ : table_(other.table_,
+ unordered_multimap::value_allocator_traits::
+ select_on_container_copy_construction(other.get_allocator()))
{
+ if (other.table_.size_) {
+ table_.copy_buckets(
+ other.table_, boost::unordered::detail::false_type());
+ }
}
template <class K, class T, class H, class P, class A>
@@ -1646,45 +1896,52 @@ unordered_multimap<K, T, H, P, A>::unordered_multimap(
unordered_multimap const& other, allocator_type const& a)
: table_(other.table_, a)
{
+ if (other.table_.size_) {
+ table_.copy_buckets(
+ other.table_, boost::unordered::detail::false_type());
+ }
}
template <class K, class T, class H, class P, class A>
-template <class InputIt>
-unordered_multimap<K, T, H, P, A>::unordered_multimap(InputIt f, InputIt l)
- : table_(boost::unordered::detail::initial_size(f, l), hasher(),
- key_equal(), allocator_type())
+unordered_multimap<K, T, H, P, A>::unordered_multimap(
+ BOOST_RV_REF(unordered_multimap) other, allocator_type const& a)
+ : table_(other.table_, a, boost::unordered::detail::move_tag())
{
- table_.insert_range(f, l);
+ if (table_.node_alloc() == other.table_.node_alloc()) {
+ table_.move_buckets_from(other.table_);
+ } else if (other.table_.size_) {
+ // TODO: Could pick new bucket size?
+ table_.move_buckets_equiv(other.table_);
+ }
}
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+
template <class K, class T, class H, class P, class A>
-template <class InputIt>
unordered_multimap<K, T, H, P, A>::unordered_multimap(
- InputIt f, InputIt l, size_type n, const hasher& hf, const key_equal& eql)
- : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql,
- allocator_type())
+ std::initializer_list<value_type> list, size_type n, const hasher& hf,
+ const key_equal& eql, const allocator_type& a)
+ : table_(
+ boost::unordered::detail::initial_size(list.begin(), list.end(), n),
+ hf, eql, a)
{
- table_.insert_range(f, l);
+ this->insert(list.begin(), list.end());
}
+#endif
+
template <class K, class T, class H, class P, class A>
-template <class InputIt>
-unordered_multimap<K, T, H, P, A>::unordered_multimap(InputIt f, InputIt l,
- size_type n, const hasher& hf, const key_equal& eql,
- const allocator_type& a)
- : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
+unordered_multimap<K, T, H, P, A>::unordered_multimap(
+ size_type n, const allocator_type& a)
+ : table_(n, hasher(), key_equal(), a)
{
- table_.insert_range(f, l);
}
template <class K, class T, class H, class P, class A>
-template <class InputIt>
-unordered_multimap<K, T, H, P, A>::unordered_multimap(InputIt f, InputIt l,
+unordered_multimap<K, T, H, P, A>::unordered_multimap(
size_type n, const hasher& hf, const allocator_type& a)
- : table_(
- boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
+ : table_(n, hf, key_equal(), a)
{
- table_.insert_range(f, l);
}
template <class K, class T, class H, class P, class A>
@@ -1694,39 +1951,30 @@ unordered_multimap<K, T, H, P, A>::unordered_multimap(
: table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
key_equal(), a)
{
- table_.insert_range(f, l);
+ this->insert(f, l);
}
template <class K, class T, class H, class P, class A>
-unordered_multimap<K, T, H, P, A>::~unordered_multimap() BOOST_NOEXCEPT
-{
-}
-
-template <class K, class T, class H, class P, class A>
-unordered_multimap<K, T, H, P, A>::unordered_multimap(
- unordered_multimap const& other)
- : table_(other.table_)
-{
-}
-
-template <class K, class T, class H, class P, class A>
-unordered_multimap<K, T, H, P, A>::unordered_multimap(
- BOOST_RV_REF(unordered_multimap) other, allocator_type const& a)
- : table_(other.table_, a, boost::unordered::detail::move_tag())
+template <class InputIt>
+unordered_multimap<K, T, H, P, A>::unordered_multimap(InputIt f, InputIt l,
+ size_type n, const hasher& hf, const allocator_type& a)
+ : table_(
+ boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
{
+ this->insert(f, l);
}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class K, class T, class H, class P, class A>
unordered_multimap<K, T, H, P, A>::unordered_multimap(
- std::initializer_list<value_type> list, size_type n, const hasher& hf,
- const key_equal& eql, const allocator_type& a)
+ std::initializer_list<value_type> list, size_type n,
+ const allocator_type& a)
: table_(
boost::unordered::detail::initial_size(list.begin(), list.end(), n),
- hf, eql, a)
+ hasher(), key_equal(), a)
{
- table_.insert_range(list.begin(), list.end());
+ this->insert(list.begin(), list.end());
}
template <class K, class T, class H, class P, class A>
@@ -1737,26 +1985,24 @@ unordered_multimap<K, T, H, P, A>::unordered_multimap(
boost::unordered::detail::initial_size(list.begin(), list.end(), n),
hf, key_equal(), a)
{
- table_.insert_range(list.begin(), list.end());
+ this->insert(list.begin(), list.end());
}
+#endif
+
template <class K, class T, class H, class P, class A>
-unordered_multimap<K, T, H, P, A>::unordered_multimap(
- std::initializer_list<value_type> list, size_type n,
- const allocator_type& a)
- : table_(
- boost::unordered::detail::initial_size(list.begin(), list.end(), n),
- hasher(), key_equal(), a)
+unordered_multimap<K, T, H, P, A>::~unordered_multimap() BOOST_NOEXCEPT
{
- table_.insert_range(list.begin(), list.end());
}
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+
template <class K, class T, class H, class P, class A>
unordered_multimap<K, T, H, P, A>& unordered_multimap<K, T, H, P, A>::operator=(
std::initializer_list<value_type> list)
{
- table_.clear();
- table_.insert_range(list.begin(), list.end());
+ this->clear();
+ this->insert(list.begin(), list.end());
return *this;
}
@@ -1767,7 +2013,13 @@ unordered_multimap<K, T, H, P, A>& unordered_multimap<K, T, H, P, A>::operator=(
template <class K, class T, class H, class P, class A>
std::size_t unordered_multimap<K, T, H, P, A>::max_size() const BOOST_NOEXCEPT
{
- return table_.max_size();
+ using namespace std;
+
+ // size <= mlf_ * count
+ return boost::unordered::detail::double_to_size(
+ ceil(static_cast<double>(table_.mlf_) *
+ static_cast<double>(table_.max_bucket_count()))) -
+ 1;
}
// modifiers
@@ -1776,7 +2028,7 @@ template <class K, class T, class H, class P, class A>
template <class InputIt>
void unordered_multimap<K, T, H, P, A>::insert(InputIt first, InputIt last)
{
- table_.insert_range(first, last);
+ table_.insert_range_equiv(first, last);
}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@@ -1784,22 +2036,37 @@ template <class K, class T, class H, class P, class A>
void unordered_multimap<K, T, H, P, A>::insert(
std::initializer_list<value_type> list)
{
- table_.insert_range(list.begin(), list.end());
+ this->insert(list.begin(), list.end());
}
#endif
template <class K, class T, class H, class P, class A>
typename unordered_multimap<K, T, H, P, A>::iterator
+unordered_multimap<K, T, H, P, A>::erase(iterator position)
+{
+ node_pointer node = table::get_node(position);
+ BOOST_ASSERT(node);
+ node_pointer next = table::next_node(node);
+ table_.erase_nodes_equiv(node, next);
+ return iterator(next);
+}
+
+template <class K, class T, class H, class P, class A>
+typename unordered_multimap<K, T, H, P, A>::iterator
unordered_multimap<K, T, H, P, A>::erase(const_iterator position)
{
- return table_.erase(position);
+ node_pointer node = table::get_node(position);
+ BOOST_ASSERT(node);
+ node_pointer next = table::next_node(node);
+ table_.erase_nodes_equiv(node, next);
+ return iterator(next);
}
template <class K, class T, class H, class P, class A>
typename unordered_multimap<K, T, H, P, A>::size_type
unordered_multimap<K, T, H, P, A>::erase(const key_type& k)
{
- return table_.erase_key(k);
+ return table_.erase_key_equiv(k);
}
template <class K, class T, class H, class P, class A>
@@ -1807,17 +2074,19 @@ typename unordered_multimap<K, T, H, P, A>::iterator
unordered_multimap<K, T, H, P, A>::erase(
const_iterator first, const_iterator last)
{
- return table_.erase_range(first, last);
-}
-
-template <class K, class T, class H, class P, class A>
-void unordered_multimap<K, T, H, P, A>::clear()
-{
- table_.clear();
+ node_pointer last_node = table::get_node(last);
+ if (first == last)
+ return iterator(last_node);
+ table_.erase_nodes_equiv(table::get_node(first), last_node);
+ return iterator(last_node);
}
template <class K, class T, class H, class P, class A>
void unordered_multimap<K, T, H, P, A>::swap(unordered_multimap& other)
+// C++17 support: BOOST_NOEXCEPT_IF(
+// value_allocator_traits::is_always_equal::value &&
+// is_nothrow_move_assignable_v<H> &&
+// is_nothrow_move_assignable_v<P>)
{
table_.swap(other.table_);
}
@@ -1860,7 +2129,6 @@ void unordered_multimap<K, T, H, P, A>::merge(
}
#endif
-#if BOOST_UNORDERED_INTEROPERABLE_NODES
template <class K, class T, class H, class P, class A>
template <typename H2, typename P2>
void unordered_multimap<K, T, H, P, A>::merge(
@@ -1882,7 +2150,6 @@ void unordered_multimap<K, T, H, P, A>::merge(
}
}
#endif
-#endif
// lookup
@@ -1906,7 +2173,8 @@ typename unordered_multimap<K, T, H, P, A>::iterator
unordered_multimap<K, T, H, P, A>::find(CompatibleKey const& k,
CompatibleHash const& hash, CompatiblePredicate const& eq)
{
- return iterator(table_.generic_find_node(k, hash, eq));
+ return iterator(
+ table_.find_node_impl(table::policy::apply_hash(hash, k), k, eq));
}
template <class K, class T, class H, class P, class A>
@@ -1915,14 +2183,16 @@ typename unordered_multimap<K, T, H, P, A>::const_iterator
unordered_multimap<K, T, H, P, A>::find(CompatibleKey const& k,
CompatibleHash const& hash, CompatiblePredicate const& eq) const
{
- return const_iterator(table_.generic_find_node(k, hash, eq));
+ return const_iterator(
+ table_.find_node_impl(table::policy::apply_hash(hash, k), k, eq));
}
template <class K, class T, class H, class P, class A>
typename unordered_multimap<K, T, H, P, A>::size_type
unordered_multimap<K, T, H, P, A>::count(const key_type& k) const
{
- return table_.count(k);
+ node_pointer n = table_.find_node(k);
+ return n ? table_.group_count(n) : 0;
}
template <class K, class T, class H, class P, class A>
@@ -1930,7 +2200,8 @@ std::pair<typename unordered_multimap<K, T, H, P, A>::iterator,
typename unordered_multimap<K, T, H, P, A>::iterator>
unordered_multimap<K, T, H, P, A>::equal_range(const key_type& k)
{
- return table_.equal_range(k);
+ node_pointer n = table_.find_node(k);
+ return std::make_pair(iterator(n), iterator(n ? table_.next_group(n) : n));
}
template <class K, class T, class H, class P, class A>
@@ -1938,7 +2209,9 @@ std::pair<typename unordered_multimap<K, T, H, P, A>::const_iterator,
typename unordered_multimap<K, T, H, P, A>::const_iterator>
unordered_multimap<K, T, H, P, A>::equal_range(const key_type& k) const
{
- return table_.equal_range(k);
+ node_pointer n = table_.find_node(k);
+ return std::make_pair(
+ const_iterator(n), const_iterator(n ? table_.next_group(n) : n));
}
template <class K, class T, class H, class P, class A>
@@ -1953,7 +2226,9 @@ unordered_multimap<K, T, H, P, A>::bucket_size(size_type n) const
template <class K, class T, class H, class P, class A>
float unordered_multimap<K, T, H, P, A>::load_factor() const BOOST_NOEXCEPT
{
- return table_.load_factor();
+ BOOST_ASSERT(table_.bucket_count_ != 0);
+ return static_cast<float>(table_.size_) /
+ static_cast<float>(table_.bucket_count_);
}
template <class K, class T, class H, class P, class A>
@@ -1971,7 +2246,8 @@ void unordered_multimap<K, T, H, P, A>::rehash(size_type n)
template <class K, class T, class H, class P, class A>
void unordered_multimap<K, T, H, P, A>::reserve(size_type n)
{
- table_.reserve(n);
+ table_.rehash(static_cast<std::size_t>(
+ std::ceil(static_cast<double>(n) / table_.mlf_)));
}
template <class K, class T, class H, class P, class A>
@@ -1984,7 +2260,7 @@ inline bool operator==(unordered_multimap<K, T, H, P, A> const& m1,
unordered_multimap<K, T, H, P, A> x;
};
#endif
- return m1.table_.equals(m2.table_);
+ return m1.table_.equals_equiv(m2.table_);
}
template <class K, class T, class H, class P, class A>
@@ -1997,12 +2273,13 @@ inline bool operator!=(unordered_multimap<K, T, H, P, A> const& m1,
unordered_multimap<K, T, H, P, A> x;
};
#endif
- return !m1.table_.equals(m2.table_);
+ return !m1.table_.equals_equiv(m2.table_);
}
template <class K, class T, class H, class P, class A>
inline void swap(unordered_multimap<K, T, H, P, A>& m1,
unordered_multimap<K, T, H, P, A>& m2)
+ BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)))
{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy
@@ -2017,10 +2294,11 @@ template <typename N, class K, class T, class A> class node_handle_map
{
BOOST_MOVABLE_BUT_NOT_COPYABLE(node_handle_map)
- template <typename Types>
- friend struct ::boost::unordered::detail::table_impl;
- template <typename Types>
- friend struct ::boost::unordered::detail::grouped_table_impl;
+ template <typename Types> friend struct ::boost::unordered::detail::table;
+ template <class K2, class T2, class H2, class P2, class A2>
+ friend class boost::unordered::unordered_map;
+ template <class K2, class T2, class H2, class P2, class A2>
+ friend class boost::unordered::unordered_multimap;
typedef typename boost::unordered::detail::rebind_wrap<A,
std::pair<K const, T> >::type value_allocator;
@@ -2043,13 +2321,7 @@ template <typename N, class K, class T, class A> class node_handle_map
bool has_alloc_;
boost::unordered::detail::value_base<value_allocator> alloc_;
- public:
- BOOST_CONSTEXPR node_handle_map() BOOST_NOEXCEPT : ptr_(), has_alloc_(false)
- {
- }
-
- /*BOOST_CONSTEXPR */ node_handle_map(
- node_pointer ptr, allocator_type const& a)
+ node_handle_map(node_pointer ptr, allocator_type const& a)
: ptr_(ptr), has_alloc_(false)
{
if (ptr_) {
@@ -2058,6 +2330,11 @@ template <typename N, class K, class T, class A> class node_handle_map
}
}
+ public:
+ BOOST_CONSTEXPR node_handle_map() BOOST_NOEXCEPT : ptr_(), has_alloc_(false)
+ {
+ }
+
~node_handle_map()
{
if (has_alloc_ && ptr_) {
diff --git a/boost/unordered/unordered_map_fwd.hpp b/boost/unordered/unordered_map_fwd.hpp
index 12855e92ad..ebac59b48f 100644
--- a/boost/unordered/unordered_map_fwd.hpp
+++ b/boost/unordered/unordered_map_fwd.hpp
@@ -30,7 +30,9 @@ template <class K, class T, class H, class P, class A>
inline bool operator!=(
unordered_map<K, T, H, P, A> const&, unordered_map<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
-inline void swap(unordered_map<K, T, H, P, A>&, unordered_map<K, T, H, P, A>&);
+inline void swap(
+ unordered_map<K, T, H, P, A>& m1, unordered_map<K, T, H, P, A>& m2)
+ BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class K, class T, class H = boost::hash<K>,
class P = std::equal_to<K>,
@@ -44,8 +46,9 @@ template <class K, class T, class H, class P, class A>
inline bool operator!=(unordered_multimap<K, T, H, P, A> const&,
unordered_multimap<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A>
-inline void swap(
- unordered_multimap<K, T, H, P, A>&, unordered_multimap<K, T, H, P, A>&);
+inline void swap(unordered_multimap<K, T, H, P, A>& m1,
+ unordered_multimap<K, T, H, P, A>& m2)
+ BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class N, class K, class T, class A> class node_handle_map;
template <class N, class K, class T, class A> struct insert_return_type_map;
diff --git a/boost/unordered/unordered_set.hpp b/boost/unordered/unordered_set.hpp
index 40d566c254..985742fff2 100644
--- a/boost/unordered/unordered_set.hpp
+++ b/boost/unordered/unordered_set.hpp
@@ -53,6 +53,8 @@ template <class T, class H, class P, class A> class unordered_set
typedef boost::unordered::detail::set<A, T, H, P> types;
typedef typename types::value_allocator_traits value_allocator_traits;
typedef typename types::table table;
+ typedef typename table::node_pointer node_pointer;
+ typedef typename table::link_pointer link_pointer;
public:
typedef typename value_allocator_traits::pointer pointer;
@@ -64,10 +66,10 @@ template <class T, class H, class P, class A> class unordered_set
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
- typedef typename table::cl_iterator const_local_iterator;
- typedef typename table::l_iterator local_iterator;
- typedef typename table::c_iterator const_iterator;
typedef typename table::iterator iterator;
+ typedef typename table::c_iterator const_iterator;
+ typedef typename table::l_iterator local_iterator;
+ typedef typename table::cl_iterator const_local_iterator;
typedef typename types::node_type node_type;
typedef typename types::insert_return_type insert_return_type;
@@ -83,59 +85,54 @@ template <class T, class H, class P, class A> class unordered_set
const key_equal& = key_equal(),
const allocator_type& = allocator_type());
- explicit unordered_set(size_type, const allocator_type&);
-
- explicit unordered_set(size_type, const hasher&, const allocator_type&);
-
- explicit unordered_set(allocator_type const&);
-
- template <class InputIt> unordered_set(InputIt, InputIt);
-
- template <class InputIt>
- unordered_set(InputIt, InputIt, size_type, const hasher& = hasher(),
- const key_equal& = key_equal());
-
template <class InputIt>
- unordered_set(InputIt, InputIt, size_type, const hasher&, const key_equal&,
- const allocator_type&);
-
- template <class InputIt>
- unordered_set(
- InputIt, InputIt, size_type, const hasher&, const allocator_type&);
-
- template <class InputIt>
- unordered_set(InputIt, InputIt, size_type, const allocator_type&);
-
- // copy/move constructors
+ unordered_set(InputIt, InputIt,
+ size_type = boost::unordered::detail::default_bucket_count,
+ const hasher& = hasher(), const key_equal& = key_equal(),
+ const allocator_type& = allocator_type());
unordered_set(unordered_set const&);
- unordered_set(unordered_set const&, allocator_type const&);
- unordered_set(BOOST_RV_REF(unordered_set), allocator_type const&);
-
-#if defined(BOOST_UNORDERED_USE_MOVE)
+#if defined(BOOST_UNORDERED_USE_MOVE) || \
+ !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_set(BOOST_RV_REF(unordered_set) other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
- }
-#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- unordered_set(unordered_set&& other)
- BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
- : table_(other.table_, boost::unordered::detail::move_tag())
- {
+ // The move is done in table_
}
#endif
+ explicit unordered_set(allocator_type const&);
+
+ unordered_set(unordered_set const&, allocator_type const&);
+
+ unordered_set(BOOST_RV_REF(unordered_set), allocator_type const&);
+
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_set(std::initializer_list<value_type>,
size_type = boost::unordered::detail::default_bucket_count,
const hasher& = hasher(), const key_equal& l = key_equal(),
const allocator_type& = allocator_type());
- unordered_set(std::initializer_list<value_type>, size_type, const hasher&,
- const allocator_type&);
+#endif
+
+ explicit unordered_set(size_type, const allocator_type&);
+
+ explicit unordered_set(size_type, const hasher&, const allocator_type&);
+
+ template <class InputIt>
+ unordered_set(InputIt, InputIt, size_type, const allocator_type&);
+
+ template <class InputIt>
+ unordered_set(
+ InputIt, InputIt, size_type, const hasher&, const allocator_type&);
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_set(
std::initializer_list<value_type>, size_type, const allocator_type&);
+
+ unordered_set(std::initializer_list<value_type>, size_type, const hasher&,
+ const allocator_type&);
#endif
// Destructor
@@ -147,26 +144,34 @@ template <class T, class H, class P, class A> class unordered_set
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_set& operator=(BOOST_COPY_ASSIGN_REF(unordered_set) x)
{
- table_.assign(x.table_);
+ table_.assign(x.table_, boost::unordered::detail::true_type());
return *this;
}
unordered_set& operator=(BOOST_RV_REF(unordered_set) x)
+ // C++17 support: BOOST_NOEXCEPT_IF(
+ // value_allocator_traits::is_always_equal::value &&
+ // is_nothrow_move_assignable_v<H> &&
+ // is_nothrow_move_assignable_v<P>)
{
- table_.move_assign(x.table_);
+ table_.move_assign(x.table_, boost::unordered::detail::true_type());
return *this;
}
#else
unordered_set& operator=(unordered_set const& x)
{
- table_.assign(x.table_);
+ table_.assign(x.table_, boost::unordered::detail::true_type());
return *this;
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_set& operator=(unordered_set&& x)
+ // C++17 support: BOOST_NOEXCEPT_IF(
+ // value_allocator_traits::is_always_equal::value &&
+ // is_nothrow_move_assignable_v<H> &&
+ // is_nothrow_move_assignable_v<P>)
{
- table_.move_assign(x.table_);
+ table_.move_assign(x.table_, boost::unordered::detail::true_type());
return *this;
}
#endif
@@ -181,14 +186,6 @@ template <class T, class H, class P, class A> class unordered_set
return table_.node_alloc();
}
- // size and capacity
-
- bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; }
-
- size_type size() const BOOST_NOEXCEPT { return table_.size_; }
-
- size_type max_size() const BOOST_NOEXCEPT;
-
// iterators
iterator begin() BOOST_NOEXCEPT { return iterator(table_.begin()); }
@@ -209,36 +206,29 @@ template <class T, class H, class P, class A> class unordered_set
const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); }
- // extract
+ // size and capacity
- node_type extract(const_iterator position)
- {
- return node_type(
- table_.extract_by_iterator(position), table_.node_alloc());
- }
+ bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; }
- node_type extract(const key_type& k)
- {
- return node_type(table_.extract_by_key(k), table_.node_alloc());
- }
+ size_type size() const BOOST_NOEXCEPT { return table_.size_; }
+
+ size_type max_size() const BOOST_NOEXCEPT;
// emplace
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
template <class... Args>
std::pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args)
{
- return table_.emplace(boost::forward<Args>(args)...);
+ return table_.emplace_unique(
+ table::extractor::extract(boost::forward<Args>(args)...),
+ boost::forward<Args>(args)...);
}
- template <class... Args>
- iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
- {
- return table_.emplace_hint(hint, boost::forward<Args>(args)...);
- }
#else
-#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
+#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
// 0 argument emplace requires special treatment in case
// the container is instantiated with a value type that
@@ -252,6 +242,56 @@ template <class T, class H, class P, class A> class unordered_set
return this->emplace(boost::move(v));
}
+#endif
+
+ template <typename A0>
+ std::pair<iterator, bool> emplace(BOOST_FWD_REF(A0) a0)
+ {
+ return table_.emplace_unique(
+ table::extractor::extract(boost::forward<A0>(a0)),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0)));
+ }
+
+ template <typename A0, typename A1>
+ std::pair<iterator, bool> emplace(
+ BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
+ {
+ return table_.emplace_unique(
+ table::extractor::extract(
+ boost::forward<A0>(a0), boost::forward<A1>(a1)),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1)));
+ }
+
+ template <typename A0, typename A1, typename A2>
+ std::pair<iterator, bool> emplace(
+ BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
+ {
+ return table_.emplace_unique(
+ table::extractor::extract(
+ boost::forward<A0>(a0), boost::forward<A1>(a1)),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1),
+ boost::forward<A2>(a2)));
+ }
+
+#endif
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template <class... Args>
+ iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
+ {
+ return table_.emplace_hint_unique(hint,
+ table::extractor::extract(boost::forward<Args>(args)...),
+ boost::forward<Args>(args)...);
+ }
+
+#else
+
+#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
+
iterator emplace_hint(const_iterator hint,
boost::unordered::detail::empty_emplace =
boost::unordered::detail::empty_emplace(),
@@ -263,76 +303,72 @@ template <class T, class H, class P, class A> class unordered_set
#endif
template <typename A0>
- std::pair<iterator, bool> emplace(BOOST_FWD_REF(A0) a0)
- {
- return table_.emplace(boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0)));
- }
-
- template <typename A0>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
{
- return table_.emplace_hint(
- hint, boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0)));
- }
-
- template <typename A0, typename A1>
- std::pair<iterator, bool> emplace(
- BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
- {
- return table_.emplace(boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0), boost::forward<A1>(a1)));
+ return table_.emplace_hint_unique(hint,
+ table::extractor::extract(boost::forward<A0>(a0)),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0)));
}
template <typename A0, typename A1>
iterator emplace_hint(
const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{
- return table_.emplace_hint(
- hint, boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0), boost::forward<A1>(a1)));
- }
-
- template <typename A0, typename A1, typename A2>
- std::pair<iterator, bool> emplace(
- BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
- {
- return table_.emplace(boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0), boost::forward<A1>(a1),
- boost::forward<A2>(a2)));
+ return table_.emplace_hint_unique(
+ hint, table::extractor::extract(
+ boost::forward<A0>(a0), boost::forward<A1>(a1)),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1)));
}
template <typename A0, typename A1, typename A2>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
- return table_.emplace_hint(
- hint, boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0), boost::forward<A1>(a1),
- boost::forward<A2>(a2)));
+ return table_.emplace_hint_unique(
+ hint, table::extractor::extract(
+ boost::forward<A0>(a0), boost::forward<A1>(a1)),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1),
+ boost::forward<A2>(a2)));
}
+#endif
+
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
std::pair<iterator, bool> emplace( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \
- return table_.emplace(boost::unordered::detail::create_emplace_args( \
- BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \
+ return table_.emplace_unique( \
+ table::extractor::extract( \
+ boost::forward<A0>(a0), boost::forward<A1>(a1)), \
+ boost::unordered::detail::create_emplace_args( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \
} \
\
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
iterator emplace_hint(const_iterator hint, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \
- return table_.emplace_hint( \
- hint, boost::unordered::detail::create_emplace_args( \
- BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \
- }
-
- BOOST_PP_REPEAT_FROM_TO(
- 4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EMPLACE, _)
+ return table_.emplace_hint_unique( \
+ hint, table::extractor::extract( \
+ boost::forward<A0>(a0), boost::forward<A1>(a1)), \
+ boost::unordered::detail::create_emplace_args( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \
+ }
+
+ BOOST_UNORDERED_EMPLACE(1, 4, _)
+ BOOST_UNORDERED_EMPLACE(1, 5, _)
+ BOOST_UNORDERED_EMPLACE(1, 6, _)
+ BOOST_UNORDERED_EMPLACE(1, 7, _)
+ BOOST_UNORDERED_EMPLACE(1, 8, _)
+ BOOST_UNORDERED_EMPLACE(1, 9, _)
+ BOOST_PP_REPEAT_FROM_TO(10, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT),
+ BOOST_UNORDERED_EMPLACE, _)
#undef BOOST_UNORDERED_EMPLACE
@@ -364,19 +400,33 @@ template <class T, class H, class P, class A> class unordered_set
void insert(std::initializer_list<value_type>);
#endif
+ // extract
+
+ node_type extract(const_iterator position)
+ {
+ return node_type(
+ table_.extract_by_iterator_unique(position), table_.node_alloc());
+ }
+
+ node_type extract(const key_type& k)
+ {
+ return node_type(table_.extract_by_key(k), table_.node_alloc());
+ }
+
insert_return_type insert(BOOST_RV_REF(node_type) np)
{
insert_return_type result;
- table_.move_insert_node_type(np, result);
+ table_.move_insert_node_type_unique(np, result);
return boost::move(result);
}
iterator insert(const_iterator hint, BOOST_RV_REF(node_type) np)
{
- return table_.move_insert_node_type_with_hint(hint, np);
+ return table_.move_insert_node_type_with_hint_unique(hint, np);
}
-#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \
+ (BOOST_COMP_GNUC && BOOST_COMP_GNUC < BOOST_VERSION_NUMBER(4, 6, 0))
private:
// Note: Use r-value node_type to insert.
insert_return_type insert(node_type&);
@@ -388,11 +438,17 @@ template <class T, class H, class P, class A> class unordered_set
iterator erase(const_iterator);
size_type erase(const key_type&);
iterator erase(const_iterator, const_iterator);
+ BOOST_UNORDERED_DEPRECATED("Use erase instead")
void quick_erase(const_iterator it) { erase(it); }
+ BOOST_UNORDERED_DEPRECATED("Use erase instead")
void erase_return_void(const_iterator it) { erase(it); }
- void clear();
void swap(unordered_set&);
+ // C++17 support: BOOST_NOEXCEPT_IF(
+ // value_allocator_traits::is_always_equal::value &&
+ // is_nothrow_move_assignable_v<H> &&
+ // is_nothrow_move_assignable_v<P>)
+ void clear() BOOST_NOEXCEPT { table_.clear_impl(); }
template <typename H2, typename P2>
void merge(boost::unordered_set<T, H2, P2, A>& source);
@@ -402,7 +458,6 @@ template <class T, class H, class P, class A> class unordered_set
void merge(boost::unordered_set<T, H2, P2, A>&& source);
#endif
-#if BOOST_UNORDERED_INTEROPERABLE_NODES
template <typename H2, typename P2>
void merge(boost::unordered_multiset<T, H2, P2, A>& source);
@@ -410,7 +465,6 @@ template <class T, class H, class P, class A> class unordered_set
template <typename H2, typename P2>
void merge(boost::unordered_multiset<T, H2, P2, A>&& source);
#endif
-#endif
// observers
@@ -476,9 +530,8 @@ template <class T, class H, class P, class A> class unordered_set
// hash policy
- float max_load_factor() const BOOST_NOEXCEPT { return table_.mlf_; }
-
float load_factor() const BOOST_NOEXCEPT;
+ float max_load_factor() const BOOST_NOEXCEPT { return table_.mlf_; }
void max_load_factor(float) BOOST_NOEXCEPT;
void rehash(size_type);
void reserve(size_type);
@@ -507,9 +560,11 @@ template <class T, class H, class P, class A> class unordered_multiset
typedef A allocator_type;
private:
- typedef boost::unordered::detail::multiset<A, T, H, P> types;
+ typedef boost::unordered::detail::set<A, T, H, P> types;
typedef typename types::value_allocator_traits value_allocator_traits;
typedef typename types::table table;
+ typedef typename table::node_pointer node_pointer;
+ typedef typename table::link_pointer link_pointer;
public:
typedef typename value_allocator_traits::pointer pointer;
@@ -521,10 +576,10 @@ template <class T, class H, class P, class A> class unordered_multiset
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
- typedef typename table::cl_iterator const_local_iterator;
- typedef typename table::l_iterator local_iterator;
- typedef typename table::c_iterator const_iterator;
typedef typename table::iterator iterator;
+ typedef typename table::c_iterator const_iterator;
+ typedef typename table::l_iterator local_iterator;
+ typedef typename table::cl_iterator const_local_iterator;
typedef typename types::node_type node_type;
private:
@@ -539,60 +594,55 @@ template <class T, class H, class P, class A> class unordered_multiset
const key_equal& = key_equal(),
const allocator_type& = allocator_type());
- explicit unordered_multiset(size_type, const allocator_type&);
-
- explicit unordered_multiset(
- size_type, const hasher&, const allocator_type&);
-
- explicit unordered_multiset(allocator_type const&);
-
- template <class InputIt> unordered_multiset(InputIt, InputIt);
-
- template <class InputIt>
- unordered_multiset(InputIt, InputIt, size_type, const hasher& = hasher(),
- const key_equal& = key_equal());
-
- template <class InputIt>
- unordered_multiset(InputIt, InputIt, size_type, const hasher&,
- const key_equal&, const allocator_type&);
-
template <class InputIt>
- unordered_multiset(
- InputIt, InputIt, size_type, const hasher&, const allocator_type&);
-
- template <class InputIt>
- unordered_multiset(InputIt, InputIt, size_type, const allocator_type&);
-
- // copy/move constructors
+ unordered_multiset(InputIt, InputIt,
+ size_type = boost::unordered::detail::default_bucket_count,
+ const hasher& = hasher(), const key_equal& = key_equal(),
+ const allocator_type& = allocator_type());
unordered_multiset(unordered_multiset const&);
- unordered_multiset(unordered_multiset const&, allocator_type const&);
- unordered_multiset(BOOST_RV_REF(unordered_multiset), allocator_type const&);
-
-#if defined(BOOST_UNORDERED_USE_MOVE)
+#if defined(BOOST_UNORDERED_USE_MOVE) || \
+ !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multiset(BOOST_RV_REF(unordered_multiset) other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
- }
-#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- unordered_multiset(unordered_multiset&& other)
- BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
- : table_(other.table_, boost::unordered::detail::move_tag())
- {
+ // The move is done in table_
}
#endif
+ explicit unordered_multiset(allocator_type const&);
+
+ unordered_multiset(unordered_multiset const&, allocator_type const&);
+
+ unordered_multiset(BOOST_RV_REF(unordered_multiset), allocator_type const&);
+
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_multiset(std::initializer_list<value_type>,
size_type = boost::unordered::detail::default_bucket_count,
const hasher& = hasher(), const key_equal& l = key_equal(),
const allocator_type& = allocator_type());
- unordered_multiset(std::initializer_list<value_type>, size_type,
- const hasher&, const allocator_type&);
+#endif
+
+ explicit unordered_multiset(size_type, const allocator_type&);
+
+ explicit unordered_multiset(
+ size_type, const hasher&, const allocator_type&);
+
+ template <class InputIt>
+ unordered_multiset(InputIt, InputIt, size_type, const allocator_type&);
+
+ template <class InputIt>
+ unordered_multiset(
+ InputIt, InputIt, size_type, const hasher&, const allocator_type&);
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_multiset(
std::initializer_list<value_type>, size_type, const allocator_type&);
+
+ unordered_multiset(std::initializer_list<value_type>, size_type,
+ const hasher&, const allocator_type&);
#endif
// Destructor
@@ -604,26 +654,34 @@ template <class T, class H, class P, class A> class unordered_multiset
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_multiset& operator=(BOOST_COPY_ASSIGN_REF(unordered_multiset) x)
{
- table_.assign(x.table_);
+ table_.assign(x.table_, boost::unordered::detail::false_type());
return *this;
}
unordered_multiset& operator=(BOOST_RV_REF(unordered_multiset) x)
+ // C++17 support: BOOST_NOEXCEPT_IF(
+ // value_allocator_traits::is_always_equal::value &&
+ // is_nothrow_move_assignable_v<H> &&
+ // is_nothrow_move_assignable_v<P>)
{
- table_.move_assign(x.table_);
+ table_.move_assign(x.table_, boost::unordered::detail::false_type());
return *this;
}
#else
unordered_multiset& operator=(unordered_multiset const& x)
{
- table_.assign(x.table_);
+ table_.assign(x.table_, boost::unordered::detail::false_type());
return *this;
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multiset& operator=(unordered_multiset&& x)
+ // C++17 support: BOOST_NOEXCEPT_IF(
+ // value_allocator_traits::is_always_equal::value &&
+ // is_nothrow_move_assignable_v<H> &&
+ // is_nothrow_move_assignable_v<P>)
{
- table_.move_assign(x.table_);
+ table_.move_assign(x.table_, boost::unordered::detail::false_type());
return *this;
}
#endif
@@ -638,14 +696,6 @@ template <class T, class H, class P, class A> class unordered_multiset
return table_.node_alloc();
}
- // size and capacity
-
- bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; }
-
- size_type size() const BOOST_NOEXCEPT { return table_.size_; }
-
- size_type max_size() const BOOST_NOEXCEPT;
-
// iterators
iterator begin() BOOST_NOEXCEPT { return iterator(table_.begin()); }
@@ -666,35 +716,28 @@ template <class T, class H, class P, class A> class unordered_multiset
const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); }
- // extract
+ // size and capacity
- node_type extract(const_iterator position)
- {
- return node_type(
- table_.extract_by_iterator(position), table_.node_alloc());
- }
+ bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; }
- node_type extract(const key_type& k)
- {
- return node_type(table_.extract_by_key(k), table_.node_alloc());
- }
+ size_type size() const BOOST_NOEXCEPT { return table_.size_; }
+
+ size_type max_size() const BOOST_NOEXCEPT;
// emplace
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
template <class... Args> iterator emplace(BOOST_FWD_REF(Args)... args)
{
- return table_.emplace(boost::forward<Args>(args)...);
+ return iterator(table_.emplace_equiv(
+ boost::unordered::detail::func::construct_node_from_args(
+ table_.node_alloc(), boost::forward<Args>(args)...)));
}
- template <class... Args>
- iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
- {
- return table_.emplace_hint(hint, boost::forward<Args>(args)...);
- }
#else
-#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
+#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
// 0 argument emplace requires special treatment in case
// the container is instantiated with a value type that
@@ -707,6 +750,55 @@ template <class T, class H, class P, class A> class unordered_multiset
return this->emplace(boost::move(v));
}
+#endif
+
+ template <typename A0> iterator emplace(BOOST_FWD_REF(A0) a0)
+ {
+ return iterator(table_.emplace_equiv(
+ boost::unordered::detail::func::construct_node_from_args(
+ table_.node_alloc(),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0)))));
+ }
+
+ template <typename A0, typename A1>
+ iterator emplace(BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
+ {
+ return iterator(table_.emplace_equiv(
+ boost::unordered::detail::func::construct_node_from_args(
+ table_.node_alloc(),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1)))));
+ }
+
+ template <typename A0, typename A1, typename A2>
+ iterator emplace(
+ BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
+ {
+ return iterator(table_.emplace_equiv(
+ boost::unordered::detail::func::construct_node_from_args(
+ table_.node_alloc(),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1),
+ boost::forward<A2>(a2)))));
+ }
+
+#endif
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template <class... Args>
+ iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
+ {
+ return iterator(table_.emplace_hint_equiv(
+ hint, boost::unordered::detail::func::construct_node_from_args(
+ table_.node_alloc(), boost::forward<Args>(args)...)));
+ }
+
+#else
+
+#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
+
iterator emplace_hint(const_iterator hint,
boost::unordered::detail::empty_emplace =
boost::unordered::detail::empty_emplace(),
@@ -717,74 +809,74 @@ template <class T, class H, class P, class A> class unordered_multiset
#endif
- template <typename A0> iterator emplace(BOOST_FWD_REF(A0) a0)
- {
- return table_.emplace(boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0)));
- }
-
template <typename A0>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
{
- return table_.emplace_hint(
- hint, boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0)));
- }
-
- template <typename A0, typename A1>
- iterator emplace(BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
- {
- return table_.emplace(boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0), boost::forward<A1>(a1)));
+ return iterator(table_.emplace_hint_equiv(
+ hint, boost::unordered::detail::func::construct_node_from_args(
+ table_.node_alloc(),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0)))));
}
template <typename A0, typename A1>
iterator emplace_hint(
const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{
- return table_.emplace_hint(
- hint, boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0), boost::forward<A1>(a1)));
- }
-
- template <typename A0, typename A1, typename A2>
- iterator emplace(
- BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
- {
- return table_.emplace(boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0), boost::forward<A1>(a1),
- boost::forward<A2>(a2)));
+ return iterator(table_.emplace_hint_equiv(
+ hint, boost::unordered::detail::func::construct_node_from_args(
+ table_.node_alloc(),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1)))));
}
template <typename A0, typename A1, typename A2>
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
- return table_.emplace_hint(
- hint, boost::unordered::detail::create_emplace_args(
- boost::forward<A0>(a0), boost::forward<A1>(a1),
- boost::forward<A2>(a2)));
+ return iterator(table_.emplace_hint_equiv(
+ hint, boost::unordered::detail::func::construct_node_from_args(
+ table_.node_alloc(),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1),
+ boost::forward<A2>(a2)))));
}
+#endif
+
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
iterator emplace(BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \
- return table_.emplace(boost::unordered::detail::create_emplace_args( \
- BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \
+ return iterator(table_.emplace_equiv( \
+ boost::unordered::detail::func::construct_node_from_args( \
+ table_.node_alloc(), \
+ boost::unordered::detail::create_emplace_args( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))))); \
} \
\
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
iterator emplace_hint(const_iterator hint, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \
- return table_.emplace_hint( \
- hint, boost::unordered::detail::create_emplace_args( \
- BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \
- }
-
- BOOST_PP_REPEAT_FROM_TO(
- 4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EMPLACE, _)
+ return iterator(table_.emplace_hint_equiv( \
+ hint, \
+ boost::unordered::detail::func::construct_node_from_args( \
+ table_.node_alloc(), \
+ boost::unordered::detail::create_emplace_args( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))))); \
+ }
+
+ BOOST_UNORDERED_EMPLACE(1, 4, _)
+ BOOST_UNORDERED_EMPLACE(1, 5, _)
+ BOOST_UNORDERED_EMPLACE(1, 6, _)
+ BOOST_UNORDERED_EMPLACE(1, 7, _)
+ BOOST_UNORDERED_EMPLACE(1, 8, _)
+ BOOST_UNORDERED_EMPLACE(1, 9, _)
+ BOOST_PP_REPEAT_FROM_TO(10, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT),
+ BOOST_UNORDERED_EMPLACE, _)
#undef BOOST_UNORDERED_EMPLACE
@@ -813,17 +905,31 @@ template <class T, class H, class P, class A> class unordered_multiset
void insert(std::initializer_list<value_type>);
#endif
+ // extract
+
+ node_type extract(const_iterator position)
+ {
+ return node_type(
+ table_.extract_by_iterator_equiv(position), table_.node_alloc());
+ }
+
+ node_type extract(const key_type& k)
+ {
+ return node_type(table_.extract_by_key(k), table_.node_alloc());
+ }
+
iterator insert(BOOST_RV_REF(node_type) np)
{
- return table_.move_insert_node_type(np);
+ return table_.move_insert_node_type_equiv(np);
}
iterator insert(const_iterator hint, BOOST_RV_REF(node_type) np)
{
- return table_.move_insert_node_type_with_hint(hint, np);
+ return table_.move_insert_node_type_with_hint_equiv(hint, np);
}
-#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \
+ (BOOST_COMP_GNUC && BOOST_COMP_GNUC < BOOST_VERSION_NUMBER(4, 6, 0))
private:
// Note: Use r-value node_type to insert.
iterator insert(node_type&);
@@ -835,11 +941,17 @@ template <class T, class H, class P, class A> class unordered_multiset
iterator erase(const_iterator);
size_type erase(const key_type&);
iterator erase(const_iterator, const_iterator);
+ BOOST_UNORDERED_DEPRECATED("Use erase instead")
void quick_erase(const_iterator it) { erase(it); }
+ BOOST_UNORDERED_DEPRECATED("Use erase instead")
void erase_return_void(const_iterator it) { erase(it); }
- void clear();
void swap(unordered_multiset&);
+ // C++17 support: BOOST_NOEXCEPT_IF(
+ // value_allocator_traits::is_always_equal::value &&
+ // is_nothrow_move_assignable_v<H> &&
+ // is_nothrow_move_assignable_v<P>)
+ void clear() BOOST_NOEXCEPT { table_.clear_impl(); }
template <typename H2, typename P2>
void merge(boost::unordered_multiset<T, H2, P2, A>& source);
@@ -849,7 +961,6 @@ template <class T, class H, class P, class A> class unordered_multiset
void merge(boost::unordered_multiset<T, H2, P2, A>&& source);
#endif
-#if BOOST_UNORDERED_INTEROPERABLE_NODES
template <typename H2, typename P2>
void merge(boost::unordered_set<T, H2, P2, A>& source);
@@ -857,7 +968,6 @@ template <class T, class H, class P, class A> class unordered_multiset
template <typename H2, typename P2>
void merge(boost::unordered_set<T, H2, P2, A>&& source);
#endif
-#endif
// observers
@@ -923,9 +1033,8 @@ template <class T, class H, class P, class A> class unordered_multiset
// hash policy
- float max_load_factor() const BOOST_NOEXCEPT { return table_.mlf_; }
-
float load_factor() const BOOST_NOEXCEPT;
+ float max_load_factor() const BOOST_NOEXCEPT { return table_.mlf_; }
void max_load_factor(float) BOOST_NOEXCEPT;
void rehash(size_type);
void reserve(size_type);
@@ -939,7 +1048,6 @@ template <class T, class H, class P, class A> class unordered_multiset
}; // class template unordered_multiset
////////////////////////////////////////////////////////////////////////////////
-
template <class T, class H, class P, class A>
unordered_set<T, H, P, A>::unordered_set()
: table_(boost::unordered::detail::default_bucket_count, hasher(),
@@ -955,16 +1063,24 @@ unordered_set<T, H, P, A>::unordered_set(size_type n, const hasher& hf,
}
template <class T, class H, class P, class A>
-unordered_set<T, H, P, A>::unordered_set(size_type n, const allocator_type& a)
- : table_(n, hasher(), key_equal(), a)
+template <class InputIt>
+unordered_set<T, H, P, A>::unordered_set(InputIt f, InputIt l, size_type n,
+ const hasher& hf, const key_equal& eql, const allocator_type& a)
+ : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
{
+ this->insert(f, l);
}
template <class T, class H, class P, class A>
-unordered_set<T, H, P, A>::unordered_set(
- size_type n, const hasher& hf, const allocator_type& a)
- : table_(n, hf, key_equal(), a)
+unordered_set<T, H, P, A>::unordered_set(unordered_set const& other)
+ : table_(other.table_,
+ unordered_set::value_allocator_traits::
+ select_on_container_copy_construction(other.get_allocator()))
{
+ if (other.table_.size_) {
+ table_.copy_buckets(
+ other.table_, boost::unordered::detail::true_type());
+ }
}
template <class T, class H, class P, class A>
@@ -979,44 +1095,51 @@ unordered_set<T, H, P, A>::unordered_set(
unordered_set const& other, allocator_type const& a)
: table_(other.table_, a)
{
+ if (other.table_.size_) {
+ table_.copy_buckets(
+ other.table_, boost::unordered::detail::true_type());
+ }
}
template <class T, class H, class P, class A>
-template <class InputIt>
-unordered_set<T, H, P, A>::unordered_set(InputIt f, InputIt l)
- : table_(boost::unordered::detail::initial_size(f, l), hasher(),
- key_equal(), allocator_type())
+unordered_set<T, H, P, A>::unordered_set(
+ BOOST_RV_REF(unordered_set) other, allocator_type const& a)
+ : table_(other.table_, a, boost::unordered::detail::move_tag())
{
- table_.insert_range(f, l);
+ if (table_.node_alloc() == other.table_.node_alloc()) {
+ table_.move_buckets_from(other.table_);
+ } else if (other.table_.size_) {
+ // TODO: Could pick new bucket size?
+ table_.move_buckets(other.table_);
+ }
}
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+
template <class T, class H, class P, class A>
-template <class InputIt>
-unordered_set<T, H, P, A>::unordered_set(
- InputIt f, InputIt l, size_type n, const hasher& hf, const key_equal& eql)
- : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql,
- allocator_type())
+unordered_set<T, H, P, A>::unordered_set(std::initializer_list<value_type> list,
+ size_type n, const hasher& hf, const key_equal& eql,
+ const allocator_type& a)
+ : table_(
+ boost::unordered::detail::initial_size(list.begin(), list.end(), n),
+ hf, eql, a)
{
- table_.insert_range(f, l);
+ this->insert(list.begin(), list.end());
}
+#endif
+
template <class T, class H, class P, class A>
-template <class InputIt>
-unordered_set<T, H, P, A>::unordered_set(InputIt f, InputIt l, size_type n,
- const hasher& hf, const key_equal& eql, const allocator_type& a)
- : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
+unordered_set<T, H, P, A>::unordered_set(size_type n, const allocator_type& a)
+ : table_(n, hasher(), key_equal(), a)
{
- table_.insert_range(f, l);
}
template <class T, class H, class P, class A>
-template <class InputIt>
-unordered_set<T, H, P, A>::unordered_set(InputIt f, InputIt l, size_type n,
- const hasher& hf, const allocator_type& a)
- : table_(
- boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
+unordered_set<T, H, P, A>::unordered_set(
+ size_type n, const hasher& hf, const allocator_type& a)
+ : table_(n, hf, key_equal(), a)
{
- table_.insert_range(f, l);
}
template <class T, class H, class P, class A>
@@ -1026,38 +1149,29 @@ unordered_set<T, H, P, A>::unordered_set(
: table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
key_equal(), a)
{
- table_.insert_range(f, l);
+ this->insert(f, l);
}
template <class T, class H, class P, class A>
-unordered_set<T, H, P, A>::~unordered_set() BOOST_NOEXCEPT
-{
-}
-
-template <class T, class H, class P, class A>
-unordered_set<T, H, P, A>::unordered_set(unordered_set const& other)
- : table_(other.table_)
-{
-}
-
-template <class T, class H, class P, class A>
-unordered_set<T, H, P, A>::unordered_set(
- BOOST_RV_REF(unordered_set) other, allocator_type const& a)
- : table_(other.table_, a, boost::unordered::detail::move_tag())
+template <class InputIt>
+unordered_set<T, H, P, A>::unordered_set(InputIt f, InputIt l, size_type n,
+ const hasher& hf, const allocator_type& a)
+ : table_(
+ boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
{
+ this->insert(f, l);
}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class T, class H, class P, class A>
unordered_set<T, H, P, A>::unordered_set(std::initializer_list<value_type> list,
- size_type n, const hasher& hf, const key_equal& eql,
- const allocator_type& a)
+ size_type n, const allocator_type& a)
: table_(
boost::unordered::detail::initial_size(list.begin(), list.end(), n),
- hf, eql, a)
+ hasher(), key_equal(), a)
{
- table_.insert_range(list.begin(), list.end());
+ this->insert(list.begin(), list.end());
}
template <class T, class H, class P, class A>
@@ -1067,25 +1181,24 @@ unordered_set<T, H, P, A>::unordered_set(std::initializer_list<value_type> list,
boost::unordered::detail::initial_size(list.begin(), list.end(), n),
hf, key_equal(), a)
{
- table_.insert_range(list.begin(), list.end());
+ this->insert(list.begin(), list.end());
}
+#endif
+
template <class T, class H, class P, class A>
-unordered_set<T, H, P, A>::unordered_set(std::initializer_list<value_type> list,
- size_type n, const allocator_type& a)
- : table_(
- boost::unordered::detail::initial_size(list.begin(), list.end(), n),
- hasher(), key_equal(), a)
+unordered_set<T, H, P, A>::~unordered_set() BOOST_NOEXCEPT
{
- table_.insert_range(list.begin(), list.end());
}
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+
template <class T, class H, class P, class A>
unordered_set<T, H, P, A>& unordered_set<T, H, P, A>::operator=(
std::initializer_list<value_type> list)
{
- table_.clear();
- table_.insert_range(list.begin(), list.end());
+ this->clear();
+ this->insert(list.begin(), list.end());
return *this;
}
@@ -1096,7 +1209,13 @@ unordered_set<T, H, P, A>& unordered_set<T, H, P, A>::operator=(
template <class T, class H, class P, class A>
std::size_t unordered_set<T, H, P, A>::max_size() const BOOST_NOEXCEPT
{
- return table_.max_size();
+ using namespace std;
+
+ // size < mlf_ * count
+ return boost::unordered::detail::double_to_size(
+ ceil(static_cast<double>(table_.mlf_) *
+ static_cast<double>(table_.max_bucket_count()))) -
+ 1;
}
// modifiers
@@ -1105,14 +1224,17 @@ template <class T, class H, class P, class A>
template <class InputIt>
void unordered_set<T, H, P, A>::insert(InputIt first, InputIt last)
{
- table_.insert_range(first, last);
+ if (first != last) {
+ table_.insert_range_unique(
+ table::extractor::extract(*first), first, last);
+ }
}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class T, class H, class P, class A>
void unordered_set<T, H, P, A>::insert(std::initializer_list<value_type> list)
{
- table_.insert_range(list.begin(), list.end());
+ this->insert(list.begin(), list.end());
}
#endif
@@ -1120,31 +1242,37 @@ template <class T, class H, class P, class A>
typename unordered_set<T, H, P, A>::iterator unordered_set<T, H, P, A>::erase(
const_iterator position)
{
- return table_.erase(position);
+ node_pointer node = table::get_node(position);
+ BOOST_ASSERT(node);
+ node_pointer next = table::next_node(node);
+ table_.erase_nodes_unique(node, next);
+ return iterator(next);
}
template <class T, class H, class P, class A>
typename unordered_set<T, H, P, A>::size_type unordered_set<T, H, P, A>::erase(
const key_type& k)
{
- return table_.erase_key(k);
+ return table_.erase_key_unique(k);
}
template <class T, class H, class P, class A>
typename unordered_set<T, H, P, A>::iterator unordered_set<T, H, P, A>::erase(
const_iterator first, const_iterator last)
{
- return table_.erase_range(first, last);
-}
-
-template <class T, class H, class P, class A>
-void unordered_set<T, H, P, A>::clear()
-{
- table_.clear();
+ node_pointer last_node = table::get_node(last);
+ if (first == last)
+ return iterator(last_node);
+ table_.erase_nodes_unique(table::get_node(first), last_node);
+ return iterator(last_node);
}
template <class T, class H, class P, class A>
void unordered_set<T, H, P, A>::swap(unordered_set& other)
+// C++17 support: BOOST_NOEXCEPT_IF(
+// value_allocator_traits::is_always_equal::value &&
+// is_nothrow_move_assignable_v<H> &&
+// is_nothrow_move_assignable_v<P>)
{
table_.swap(other.table_);
}
@@ -1170,7 +1298,7 @@ template <typename H2, typename P2>
void unordered_set<T, H, P, A>::merge(
boost::unordered_set<T, H2, P2, A>& source)
{
- table_.merge_impl(source.table_);
+ table_.merge_unique(source.table_);
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
@@ -1179,17 +1307,16 @@ template <typename H2, typename P2>
void unordered_set<T, H, P, A>::merge(
boost::unordered_set<T, H2, P2, A>&& source)
{
- table_.merge_impl(source.table_);
+ table_.merge_unique(source.table_);
}
#endif
-#if BOOST_UNORDERED_INTEROPERABLE_NODES
template <class T, class H, class P, class A>
template <typename H2, typename P2>
void unordered_set<T, H, P, A>::merge(
boost::unordered_multiset<T, H2, P2, A>& source)
{
- table_.merge_impl(source.table_);
+ table_.merge_unique(source.table_);
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
@@ -1198,10 +1325,9 @@ template <typename H2, typename P2>
void unordered_set<T, H, P, A>::merge(
boost::unordered_multiset<T, H2, P2, A>&& source)
{
- table_.merge_impl(source.table_);
+ table_.merge_unique(source.table_);
}
#endif
-#endif
// lookup
@@ -1218,14 +1344,15 @@ typename unordered_set<T, H, P, A>::const_iterator
unordered_set<T, H, P, A>::find(CompatibleKey const& k,
CompatibleHash const& hash, CompatiblePredicate const& eq) const
{
- return const_iterator(table_.generic_find_node(k, hash, eq));
+ return const_iterator(
+ table_.find_node_impl(table::policy::apply_hash(hash, k), k, eq));
}
template <class T, class H, class P, class A>
typename unordered_set<T, H, P, A>::size_type unordered_set<T, H, P, A>::count(
const key_type& k) const
{
- return table_.count(k);
+ return table_.find_node(k) ? 1 : 0;
}
template <class T, class H, class P, class A>
@@ -1233,7 +1360,9 @@ std::pair<typename unordered_set<T, H, P, A>::const_iterator,
typename unordered_set<T, H, P, A>::const_iterator>
unordered_set<T, H, P, A>::equal_range(const key_type& k) const
{
- return table_.equal_range(k);
+ node_pointer n = table_.find_node(k);
+ return std::make_pair(
+ const_iterator(n), const_iterator(n ? table::next_node(n) : n));
}
template <class T, class H, class P, class A>
@@ -1248,7 +1377,9 @@ unordered_set<T, H, P, A>::bucket_size(size_type n) const
template <class T, class H, class P, class A>
float unordered_set<T, H, P, A>::load_factor() const BOOST_NOEXCEPT
{
- return table_.load_factor();
+ BOOST_ASSERT(table_.bucket_count_ != 0);
+ return static_cast<float>(table_.size_) /
+ static_cast<float>(table_.bucket_count_);
}
template <class T, class H, class P, class A>
@@ -1266,7 +1397,8 @@ void unordered_set<T, H, P, A>::rehash(size_type n)
template <class T, class H, class P, class A>
void unordered_set<T, H, P, A>::reserve(size_type n)
{
- table_.reserve(n);
+ table_.rehash(static_cast<std::size_t>(
+ std::ceil(static_cast<double>(n) / table_.mlf_)));
}
template <class T, class H, class P, class A>
@@ -1279,7 +1411,7 @@ inline bool operator==(
unordered_set<T, H, P, A> x;
};
#endif
- return m1.table_.equals(m2.table_);
+ return m1.table_.equals_unique(m2.table_);
}
template <class T, class H, class P, class A>
@@ -1292,11 +1424,12 @@ inline bool operator!=(
unordered_set<T, H, P, A> x;
};
#endif
- return !m1.table_.equals(m2.table_);
+ return !m1.table_.equals_unique(m2.table_);
}
template <class T, class H, class P, class A>
inline void swap(unordered_set<T, H, P, A>& m1, unordered_set<T, H, P, A>& m2)
+ BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)))
{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy
@@ -1324,17 +1457,26 @@ unordered_multiset<T, H, P, A>::unordered_multiset(size_type n,
}
template <class T, class H, class P, class A>
-unordered_multiset<T, H, P, A>::unordered_multiset(
- size_type n, const allocator_type& a)
- : table_(n, hasher(), key_equal(), a)
+template <class InputIt>
+unordered_multiset<T, H, P, A>::unordered_multiset(InputIt f, InputIt l,
+ size_type n, const hasher& hf, const key_equal& eql,
+ const allocator_type& a)
+ : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
{
+ this->insert(f, l);
}
template <class T, class H, class P, class A>
unordered_multiset<T, H, P, A>::unordered_multiset(
- size_type n, const hasher& hf, const allocator_type& a)
- : table_(n, hf, key_equal(), a)
+ unordered_multiset const& other)
+ : table_(other.table_,
+ unordered_multiset::value_allocator_traits::
+ select_on_container_copy_construction(other.get_allocator()))
{
+ if (other.table_.size_) {
+ table_.copy_buckets(
+ other.table_, boost::unordered::detail::false_type());
+ }
}
template <class T, class H, class P, class A>
@@ -1349,45 +1491,52 @@ unordered_multiset<T, H, P, A>::unordered_multiset(
unordered_multiset const& other, allocator_type const& a)
: table_(other.table_, a)
{
+ if (other.table_.size_) {
+ table_.copy_buckets(
+ other.table_, boost::unordered::detail::false_type());
+ }
}
template <class T, class H, class P, class A>
-template <class InputIt>
-unordered_multiset<T, H, P, A>::unordered_multiset(InputIt f, InputIt l)
- : table_(boost::unordered::detail::initial_size(f, l), hasher(),
- key_equal(), allocator_type())
+unordered_multiset<T, H, P, A>::unordered_multiset(
+ BOOST_RV_REF(unordered_multiset) other, allocator_type const& a)
+ : table_(other.table_, a, boost::unordered::detail::move_tag())
{
- table_.insert_range(f, l);
+ if (table_.node_alloc() == other.table_.node_alloc()) {
+ table_.move_buckets_from(other.table_);
+ } else if (other.table_.size_) {
+ // TODO: Could pick new bucket size?
+ table_.move_buckets_equiv(other.table_);
+ }
}
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+
template <class T, class H, class P, class A>
-template <class InputIt>
unordered_multiset<T, H, P, A>::unordered_multiset(
- InputIt f, InputIt l, size_type n, const hasher& hf, const key_equal& eql)
- : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql,
- allocator_type())
+ std::initializer_list<value_type> list, size_type n, const hasher& hf,
+ const key_equal& eql, const allocator_type& a)
+ : table_(
+ boost::unordered::detail::initial_size(list.begin(), list.end(), n),
+ hf, eql, a)
{
- table_.insert_range(f, l);
+ this->insert(list.begin(), list.end());
}
+#endif
+
template <class T, class H, class P, class A>
-template <class InputIt>
-unordered_multiset<T, H, P, A>::unordered_multiset(InputIt f, InputIt l,
- size_type n, const hasher& hf, const key_equal& eql,
- const allocator_type& a)
- : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
+unordered_multiset<T, H, P, A>::unordered_multiset(
+ size_type n, const allocator_type& a)
+ : table_(n, hasher(), key_equal(), a)
{
- table_.insert_range(f, l);
}
template <class T, class H, class P, class A>
-template <class InputIt>
-unordered_multiset<T, H, P, A>::unordered_multiset(InputIt f, InputIt l,
+unordered_multiset<T, H, P, A>::unordered_multiset(
size_type n, const hasher& hf, const allocator_type& a)
- : table_(
- boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
+ : table_(n, hf, key_equal(), a)
{
- table_.insert_range(f, l);
}
template <class T, class H, class P, class A>
@@ -1397,39 +1546,30 @@ unordered_multiset<T, H, P, A>::unordered_multiset(
: table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
key_equal(), a)
{
- table_.insert_range(f, l);
-}
-
-template <class T, class H, class P, class A>
-unordered_multiset<T, H, P, A>::~unordered_multiset() BOOST_NOEXCEPT
-{
+ this->insert(f, l);
}
template <class T, class H, class P, class A>
-unordered_multiset<T, H, P, A>::unordered_multiset(
- unordered_multiset const& other)
- : table_(other.table_)
-{
-}
-
-template <class T, class H, class P, class A>
-unordered_multiset<T, H, P, A>::unordered_multiset(
- BOOST_RV_REF(unordered_multiset) other, allocator_type const& a)
- : table_(other.table_, a, boost::unordered::detail::move_tag())
+template <class InputIt>
+unordered_multiset<T, H, P, A>::unordered_multiset(InputIt f, InputIt l,
+ size_type n, const hasher& hf, const allocator_type& a)
+ : table_(
+ boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
{
+ this->insert(f, l);
}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class T, class H, class P, class A>
unordered_multiset<T, H, P, A>::unordered_multiset(
- std::initializer_list<value_type> list, size_type n, const hasher& hf,
- const key_equal& eql, const allocator_type& a)
+ std::initializer_list<value_type> list, size_type n,
+ const allocator_type& a)
: table_(
boost::unordered::detail::initial_size(list.begin(), list.end(), n),
- hf, eql, a)
+ hasher(), key_equal(), a)
{
- table_.insert_range(list.begin(), list.end());
+ this->insert(list.begin(), list.end());
}
template <class T, class H, class P, class A>
@@ -1440,26 +1580,24 @@ unordered_multiset<T, H, P, A>::unordered_multiset(
boost::unordered::detail::initial_size(list.begin(), list.end(), n),
hf, key_equal(), a)
{
- table_.insert_range(list.begin(), list.end());
+ this->insert(list.begin(), list.end());
}
+#endif
+
template <class T, class H, class P, class A>
-unordered_multiset<T, H, P, A>::unordered_multiset(
- std::initializer_list<value_type> list, size_type n,
- const allocator_type& a)
- : table_(
- boost::unordered::detail::initial_size(list.begin(), list.end(), n),
- hasher(), key_equal(), a)
+unordered_multiset<T, H, P, A>::~unordered_multiset() BOOST_NOEXCEPT
{
- table_.insert_range(list.begin(), list.end());
}
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+
template <class T, class H, class P, class A>
unordered_multiset<T, H, P, A>& unordered_multiset<T, H, P, A>::operator=(
std::initializer_list<value_type> list)
{
- table_.clear();
- table_.insert_range(list.begin(), list.end());
+ this->clear();
+ this->insert(list.begin(), list.end());
return *this;
}
@@ -1470,7 +1608,13 @@ unordered_multiset<T, H, P, A>& unordered_multiset<T, H, P, A>::operator=(
template <class T, class H, class P, class A>
std::size_t unordered_multiset<T, H, P, A>::max_size() const BOOST_NOEXCEPT
{
- return table_.max_size();
+ using namespace std;
+
+ // size < mlf_ * count
+ return boost::unordered::detail::double_to_size(
+ ceil(static_cast<double>(table_.mlf_) *
+ static_cast<double>(table_.max_bucket_count()))) -
+ 1;
}
// modifiers
@@ -1479,7 +1623,7 @@ template <class T, class H, class P, class A>
template <class InputIt>
void unordered_multiset<T, H, P, A>::insert(InputIt first, InputIt last)
{
- table_.insert_range(first, last);
+ table_.insert_range_equiv(first, last);
}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@@ -1487,7 +1631,7 @@ template <class T, class H, class P, class A>
void unordered_multiset<T, H, P, A>::insert(
std::initializer_list<value_type> list)
{
- table_.insert_range(list.begin(), list.end());
+ this->insert(list.begin(), list.end());
}
#endif
@@ -1495,31 +1639,37 @@ template <class T, class H, class P, class A>
typename unordered_multiset<T, H, P, A>::iterator
unordered_multiset<T, H, P, A>::erase(const_iterator position)
{
- return table_.erase(position);
+ node_pointer node = table::get_node(position);
+ BOOST_ASSERT(node);
+ node_pointer next = table::next_node(node);
+ table_.erase_nodes_equiv(node, next);
+ return iterator(next);
}
template <class T, class H, class P, class A>
typename unordered_multiset<T, H, P, A>::size_type
unordered_multiset<T, H, P, A>::erase(const key_type& k)
{
- return table_.erase_key(k);
+ return table_.erase_key_equiv(k);
}
template <class T, class H, class P, class A>
typename unordered_multiset<T, H, P, A>::iterator
unordered_multiset<T, H, P, A>::erase(const_iterator first, const_iterator last)
{
- return table_.erase_range(first, last);
-}
-
-template <class T, class H, class P, class A>
-void unordered_multiset<T, H, P, A>::clear()
-{
- table_.clear();
+ node_pointer last_node = table::get_node(last);
+ if (first == last)
+ return iterator(last_node);
+ table_.erase_nodes_equiv(table::get_node(first), last_node);
+ return iterator(last_node);
}
template <class T, class H, class P, class A>
void unordered_multiset<T, H, P, A>::swap(unordered_multiset& other)
+// C++17 support: BOOST_NOEXCEPT_IF(
+// value_allocator_traits::is_always_equal::value &&
+// is_nothrow_move_assignable_v<H> &&
+// is_nothrow_move_assignable_v<P>)
{
table_.swap(other.table_);
}
@@ -1562,7 +1712,6 @@ void unordered_multiset<T, H, P, A>::merge(
}
#endif
-#if BOOST_UNORDERED_INTEROPERABLE_NODES
template <class T, class H, class P, class A>
template <typename H2, typename P2>
void unordered_multiset<T, H, P, A>::merge(
@@ -1584,7 +1733,6 @@ void unordered_multiset<T, H, P, A>::merge(
}
}
#endif
-#endif
// lookup
@@ -1601,14 +1749,16 @@ typename unordered_multiset<T, H, P, A>::const_iterator
unordered_multiset<T, H, P, A>::find(CompatibleKey const& k,
CompatibleHash const& hash, CompatiblePredicate const& eq) const
{
- return const_iterator(table_.generic_find_node(k, hash, eq));
+ return const_iterator(
+ table_.find_node_impl(table::policy::apply_hash(hash, k), k, eq));
}
template <class T, class H, class P, class A>
typename unordered_multiset<T, H, P, A>::size_type
unordered_multiset<T, H, P, A>::count(const key_type& k) const
{
- return table_.count(k);
+ node_pointer n = table_.find_node(k);
+ return n ? table_.group_count(n) : 0;
}
template <class T, class H, class P, class A>
@@ -1616,7 +1766,9 @@ std::pair<typename unordered_multiset<T, H, P, A>::const_iterator,
typename unordered_multiset<T, H, P, A>::const_iterator>
unordered_multiset<T, H, P, A>::equal_range(const key_type& k) const
{
- return table_.equal_range(k);
+ node_pointer n = table_.find_node(k);
+ return std::make_pair(
+ const_iterator(n), const_iterator(n ? table_.next_group(n) : n));
}
template <class T, class H, class P, class A>
@@ -1631,7 +1783,9 @@ unordered_multiset<T, H, P, A>::bucket_size(size_type n) const
template <class T, class H, class P, class A>
float unordered_multiset<T, H, P, A>::load_factor() const BOOST_NOEXCEPT
{
- return table_.load_factor();
+ BOOST_ASSERT(table_.bucket_count_ != 0);
+ return static_cast<float>(table_.size_) /
+ static_cast<float>(table_.bucket_count_);
}
template <class T, class H, class P, class A>
@@ -1649,7 +1803,8 @@ void unordered_multiset<T, H, P, A>::rehash(size_type n)
template <class T, class H, class P, class A>
void unordered_multiset<T, H, P, A>::reserve(size_type n)
{
- table_.reserve(n);
+ table_.rehash(static_cast<std::size_t>(
+ std::ceil(static_cast<double>(n) / table_.mlf_)));
}
template <class T, class H, class P, class A>
@@ -1662,7 +1817,7 @@ inline bool operator==(unordered_multiset<T, H, P, A> const& m1,
unordered_multiset<T, H, P, A> x;
};
#endif
- return m1.table_.equals(m2.table_);
+ return m1.table_.equals_equiv(m2.table_);
}
template <class T, class H, class P, class A>
@@ -1675,12 +1830,13 @@ inline bool operator!=(unordered_multiset<T, H, P, A> const& m1,
unordered_multiset<T, H, P, A> x;
};
#endif
- return !m1.table_.equals(m2.table_);
+ return !m1.table_.equals_equiv(m2.table_);
}
template <class T, class H, class P, class A>
inline void swap(
unordered_multiset<T, H, P, A>& m1, unordered_multiset<T, H, P, A>& m2)
+ BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)))
{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy
@@ -1695,10 +1851,11 @@ template <typename N, typename T, typename A> class node_handle_set
{
BOOST_MOVABLE_BUT_NOT_COPYABLE(node_handle_set)
- template <typename Types>
- friend struct ::boost::unordered::detail::table_impl;
- template <typename Types>
- friend struct ::boost::unordered::detail::grouped_table_impl;
+ template <typename Types> friend struct ::boost::unordered::detail::table;
+ template <class T2, class H2, class P2, class A2>
+ friend class unordered_set;
+ template <class T2, class H2, class P2, class A2>
+ friend class unordered_multiset;
typedef typename boost::unordered::detail::rebind_wrap<A, T>::type
value_allocator;
@@ -1720,13 +1877,7 @@ template <typename N, typename T, typename A> class node_handle_set
bool has_alloc_;
boost::unordered::detail::value_base<value_allocator> alloc_;
- public:
- BOOST_CONSTEXPR node_handle_set() BOOST_NOEXCEPT : ptr_(), has_alloc_(false)
- {
- }
-
- /*BOOST_CONSTEXPR */ node_handle_set(
- node_pointer ptr, allocator_type const& a)
+ node_handle_set(node_pointer ptr, allocator_type const& a)
: ptr_(ptr), has_alloc_(false)
{
if (ptr_) {
@@ -1735,6 +1886,11 @@ template <typename N, typename T, typename A> class node_handle_set
}
}
+ public:
+ BOOST_CONSTEXPR node_handle_set() BOOST_NOEXCEPT : ptr_(), has_alloc_(false)
+ {
+ }
+
~node_handle_set()
{
if (has_alloc_ && ptr_) {
diff --git a/boost/unordered/unordered_set_fwd.hpp b/boost/unordered/unordered_set_fwd.hpp
index d3a3b51e74..24842c80d2 100644
--- a/boost/unordered/unordered_set_fwd.hpp
+++ b/boost/unordered/unordered_set_fwd.hpp
@@ -29,7 +29,8 @@ template <class T, class H, class P, class A>
inline bool operator!=(
unordered_set<T, H, P, A> const&, unordered_set<T, H, P, A> const&);
template <class T, class H, class P, class A>
-inline void swap(unordered_set<T, H, P, A>& m1, unordered_set<T, H, P, A>& m2);
+inline void swap(unordered_set<T, H, P, A>& m1, unordered_set<T, H, P, A>& m2)
+ BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class T, class H = boost::hash<T>, class P = std::equal_to<T>,
class A = std::allocator<T> >
@@ -43,7 +44,8 @@ inline bool operator!=(unordered_multiset<T, H, P, A> const&,
unordered_multiset<T, H, P, A> const&);
template <class T, class H, class P, class A>
inline void swap(
- unordered_multiset<T, H, P, A>& m1, unordered_multiset<T, H, P, A>& m2);
+ unordered_multiset<T, H, P, A>& m1, unordered_multiset<T, H, P, A>& m2)
+ BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class N, class T, class A> class node_handle_set;
template <class N, class T, class A> struct insert_return_type_set;
diff --git a/boost/utility/result_of.hpp b/boost/utility/result_of.hpp
index 206ae3088a..cb16d099b6 100644
--- a/boost/utility/result_of.hpp
+++ b/boost/utility/result_of.hpp
@@ -201,6 +201,11 @@ struct tr1_result_of_impl<F, FArgs, false>
#define BOOST_PP_ITERATION_PARAMS_1 (3,(0,BOOST_RESULT_OF_NUM_ARGS,<boost/utility/detail/result_of_iterate.hpp>))
#include BOOST_PP_ITERATE()
+#if 0
+// inform dependency trackers, as they can't see through macro includes
+#include <boost/utility/detail/result_of_iterate.hpp>
+#endif
+
#else
# define BOOST_NO_RESULT_OF 1
#endif
diff --git a/boost/utility/string_view.hpp b/boost/utility/string_view.hpp
index 425d7d2de3..09d52d2d34 100644
--- a/boost/utility/string_view.hpp
+++ b/boost/utility/string_view.hpp
@@ -368,7 +368,7 @@ namespace boost {
// Comparison operators
// Equality
template<typename charT, typename traits>
- inline bool operator==(basic_string_view<charT, traits> x,
+ inline BOOST_CXX14_CONSTEXPR bool operator==(basic_string_view<charT, traits> x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
if (x.size () != y.size ()) return false;
return x.compare(y) == 0;
@@ -376,7 +376,7 @@ namespace boost {
// Inequality
template<typename charT, typename traits>
- inline bool operator!=(basic_string_view<charT, traits> x,
+ inline BOOST_CXX14_CONSTEXPR bool operator!=(basic_string_view<charT, traits> x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
if ( x.size () != y.size ()) return true;
return x.compare(y) != 0;
@@ -384,173 +384,173 @@ namespace boost {
// Less than
template<typename charT, typename traits>
- inline bool operator<(basic_string_view<charT, traits> x,
+ inline BOOST_CXX14_CONSTEXPR bool operator<(basic_string_view<charT, traits> x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return x.compare(y) < 0;
}
// Greater than
template<typename charT, typename traits>
- inline bool operator>(basic_string_view<charT, traits> x,
+ inline BOOST_CXX14_CONSTEXPR bool operator>(basic_string_view<charT, traits> x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return x.compare(y) > 0;
}
// Less than or equal to
template<typename charT, typename traits>
- inline bool operator<=(basic_string_view<charT, traits> x,
+ inline BOOST_CXX14_CONSTEXPR bool operator<=(basic_string_view<charT, traits> x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return x.compare(y) <= 0;
}
// Greater than or equal to
template<typename charT, typename traits>
- inline bool operator>=(basic_string_view<charT, traits> x,
+ inline BOOST_CXX14_CONSTEXPR bool operator>=(basic_string_view<charT, traits> x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return x.compare(y) >= 0;
}
// "sufficient additional overloads of comparison functions"
template<typename charT, typename traits, typename Allocator>
- inline bool operator==(basic_string_view<charT, traits> x,
+ inline BOOST_CXX14_CONSTEXPR bool operator==(basic_string_view<charT, traits> x,
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
return x == basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
- inline bool operator==(const std::basic_string<charT, traits, Allocator> & x,
+ inline BOOST_CXX14_CONSTEXPR bool operator==(const std::basic_string<charT, traits, Allocator> & x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) == y;
}
template<typename charT, typename traits>
- inline bool operator==(basic_string_view<charT, traits> x,
+ inline BOOST_CXX14_CONSTEXPR bool operator==(basic_string_view<charT, traits> x,
const charT * y) BOOST_NOEXCEPT {
return x == basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits>
- inline bool operator==(const charT * x,
+ inline BOOST_CXX14_CONSTEXPR bool operator==(const charT * x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) == y;
}
template<typename charT, typename traits, typename Allocator>
- inline bool operator!=(basic_string_view<charT, traits> x,
+ inline BOOST_CXX14_CONSTEXPR bool operator!=(basic_string_view<charT, traits> x,
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
return x != basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
- inline bool operator!=(const std::basic_string<charT, traits, Allocator> & x,
+ inline BOOST_CXX14_CONSTEXPR bool operator!=(const std::basic_string<charT, traits, Allocator> & x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) != y;
}
template<typename charT, typename traits>
- inline bool operator!=(basic_string_view<charT, traits> x,
+ inline BOOST_CXX14_CONSTEXPR bool operator!=(basic_string_view<charT, traits> x,
const charT * y) BOOST_NOEXCEPT {
return x != basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits>
- inline bool operator!=(const charT * x,
+ inline BOOST_CXX14_CONSTEXPR bool operator!=(const charT * x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) != y;
}
template<typename charT, typename traits, typename Allocator>
- inline bool operator<(basic_string_view<charT, traits> x,
+ inline BOOST_CXX14_CONSTEXPR bool operator<(basic_string_view<charT, traits> x,
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
return x < basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
- inline bool operator<(const std::basic_string<charT, traits, Allocator> & x,
+ inline BOOST_CXX14_CONSTEXPR bool operator<(const std::basic_string<charT, traits, Allocator> & x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) < y;
}
template<typename charT, typename traits>
- inline bool operator<(basic_string_view<charT, traits> x,
+ inline BOOST_CXX14_CONSTEXPR bool operator<(basic_string_view<charT, traits> x,
const charT * y) BOOST_NOEXCEPT {
return x < basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits>
- inline bool operator<(const charT * x,
+ inline BOOST_CXX14_CONSTEXPR bool operator<(const charT * x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) < y;
}
template<typename charT, typename traits, typename Allocator>
- inline bool operator>(basic_string_view<charT, traits> x,
+ inline BOOST_CXX14_CONSTEXPR bool operator>(basic_string_view<charT, traits> x,
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
return x > basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
- inline bool operator>(const std::basic_string<charT, traits, Allocator> & x,
+ inline BOOST_CXX14_CONSTEXPR bool operator>(const std::basic_string<charT, traits, Allocator> & x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) > y;
}
template<typename charT, typename traits>
- inline bool operator>(basic_string_view<charT, traits> x,
+ inline BOOST_CXX14_CONSTEXPR bool operator>(basic_string_view<charT, traits> x,
const charT * y) BOOST_NOEXCEPT {
return x > basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits>
- inline bool operator>(const charT * x,
+ inline BOOST_CXX14_CONSTEXPR bool operator>(const charT * x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) > y;
}
template<typename charT, typename traits, typename Allocator>
- inline bool operator<=(basic_string_view<charT, traits> x,
+ inline BOOST_CXX14_CONSTEXPR bool operator<=(basic_string_view<charT, traits> x,
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
return x <= basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
- inline bool operator<=(const std::basic_string<charT, traits, Allocator> & x,
+ inline BOOST_CXX14_CONSTEXPR bool operator<=(const std::basic_string<charT, traits, Allocator> & x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) <= y;
}
template<typename charT, typename traits>
- inline bool operator<=(basic_string_view<charT, traits> x,
+ inline BOOST_CXX14_CONSTEXPR bool operator<=(basic_string_view<charT, traits> x,
const charT * y) BOOST_NOEXCEPT {
return x <= basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits>
- inline bool operator<=(const charT * x,
+ inline BOOST_CXX14_CONSTEXPR bool operator<=(const charT * x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) <= y;
}
template<typename charT, typename traits, typename Allocator>
- inline bool operator>=(basic_string_view<charT, traits> x,
+ inline BOOST_CXX14_CONSTEXPR bool operator>=(basic_string_view<charT, traits> x,
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
return x >= basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
- inline bool operator>=(const std::basic_string<charT, traits, Allocator> & x,
+ inline BOOST_CXX14_CONSTEXPR bool operator>=(const std::basic_string<charT, traits, Allocator> & x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) >= y;
}
template<typename charT, typename traits>
- inline bool operator>=(basic_string_view<charT, traits> x,
+ inline BOOST_CXX14_CONSTEXPR bool operator>=(basic_string_view<charT, traits> x,
const charT * y) BOOST_NOEXCEPT {
return x >= basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits>
- inline bool operator>=(const charT * x,
+ inline BOOST_CXX14_CONSTEXPR bool operator>=(const charT * x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) >= y;
}
diff --git a/boost/uuid/random_generator.hpp b/boost/uuid/random_generator.hpp
index 7ca025b74f..6d32d818a0 100644
--- a/boost/uuid/random_generator.hpp
+++ b/boost/uuid/random_generator.hpp
@@ -13,6 +13,7 @@
#include <boost/random/uniform_int.hpp>
#include <boost/random/variate_generator.hpp>
#include <boost/random/mersenne_twister.hpp>
+#include <boost/core/null_deleter.hpp>
#include <boost/assert.hpp>
#include <boost/shared_ptr.hpp>
#include <limits>
@@ -27,11 +28,6 @@ private:
typedef uniform_int<unsigned long> distribution_type;
typedef variate_generator<UniformRandomNumberGenerator*, distribution_type> generator_type;
- struct null_deleter
- {
- void operator()(void const *) const {}
- };
-
public:
typedef uuid result_type;
@@ -53,7 +49,7 @@ public:
// keep a reference to a random number generator
// don't seed a given random number generator
explicit basic_random_generator(UniformRandomNumberGenerator& gen)
- : pURNG(&gen, null_deleter())
+ : pURNG(&gen, boost::null_deleter())
, generator
( pURNG.get()
, distribution_type
@@ -66,7 +62,7 @@ public:
// keep a pointer to a random number generator
// don't seed a given random number generator
explicit basic_random_generator(UniformRandomNumberGenerator* pGen)
- : pURNG(pGen, null_deleter())
+ : pURNG(pGen, boost::null_deleter())
, generator
( pURNG.get()
, distribution_type
diff --git a/boost/variant/get.hpp b/boost/variant/get.hpp
index f3eb84dc29..fd702ba60c 100644
--- a/boost/variant/get.hpp
+++ b/boost/variant/get.hpp
@@ -22,9 +22,11 @@
#include <boost/utility/addressof.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/variant/detail/element_index.hpp>
+#include <boost/variant/detail/move.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/add_pointer.hpp>
+#include <boost/type_traits/is_lvalue_reference.hpp>
namespace boost {
@@ -170,7 +172,23 @@ relaxed_get(
return *result;
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
+inline
+ U&&
+relaxed_get(
+ boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >&& operand
+ BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
+ )
+{
+ typedef typename add_pointer<U>::type U_ptr;
+ U_ptr result = relaxed_get<U>(boost::addressof(operand));
+ if (!result)
+ boost::throw_exception(bad_get());
+ return static_cast<U&&>(*result);
+}
+#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// strict_get<U>(variant) methods
@@ -243,6 +261,30 @@ strict_get(
return relaxed_get<U>(operand);
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
+inline
+ U&&
+strict_get(
+ boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >&& operand
+ BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
+ )
+{
+ BOOST_STATIC_ASSERT_MSG(
+ (!boost::is_lvalue_reference<U>::value),
+ "remove ampersand '&' from template type U in boost::get<U>(boost::variant<T...>&&) "
+ );
+
+ BOOST_STATIC_ASSERT_MSG(
+ (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
+ "boost::variant does not contain specified type U, "
+ "call to boost::get<U>(const boost::variant<T...>&) will always throw boost::bad_get exception"
+ );
+
+ return relaxed_get<U>(detail::variant::move(operand));
+}
+#endif
+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// get<U>(variant) methods
//
@@ -308,6 +350,23 @@ get(
#endif
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
+inline
+ U&&
+get(
+ boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >&& operand
+ BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
+ )
+{
+#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
+ return relaxed_get<U>(detail::variant::move(operand));
+#else
+ return strict_get<U>(detail::variant::move(operand));
+#endif
+}
+#endif
+
} // namespace boost
#endif // BOOST_VARIANT_GET_HPP
diff --git a/boost/variant/polymorphic_get.hpp b/boost/variant/polymorphic_get.hpp
index 1a98382be6..c4ec0bfaaa 100644
--- a/boost/variant/polymorphic_get.hpp
+++ b/boost/variant/polymorphic_get.hpp
@@ -25,6 +25,7 @@
#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/add_pointer.hpp>
#include <boost/type_traits/is_base_of.hpp>
+#include <boost/type_traits/is_const.hpp>
namespace boost {
diff --git a/boost/variant/variant.hpp b/boost/variant/variant.hpp
index 1c64447428..c3e2ccf8e5 100644
--- a/boost/variant/variant.hpp
+++ b/boost/variant/variant.hpp
@@ -71,10 +71,12 @@
#include <boost/mpl/front.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/if.hpp>
+#include <boost/mpl/insert_range.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/iterator_range.hpp>
#include <boost/mpl/iter_fold_if.hpp>
+#include <boost/mpl/list.hpp>
#include <boost/mpl/logical.hpp>
#include <boost/mpl/max_element.hpp>
#include <boost/mpl/next.hpp>
@@ -386,7 +388,7 @@ public: // visitor interfaces
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551)) || \
BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
- operand; // suppresses warnings
+ (void)operand; // suppresses warnings
#endif
BOOST_VARIANT_AUX_RETURN_VOID;
@@ -2452,16 +2454,20 @@ struct make_variant_over
private: // precondition assertions
BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence<Types>::value ));
+ typedef typename boost::mpl::insert_range<
+ boost::mpl::list<>
+ , boost::mpl::end< boost::mpl::list<> >::type
+ , Types
+ >::type copied_sequence_t;
public: // metafunction result
typedef variant<
- detail::variant::over_sequence< Types >
+ detail::variant::over_sequence<copied_sequence_t>
> type;
};
-
///////////////////////////////////////////////////////////////////////////////
// function template swap
//
diff --git a/boost/version.hpp b/boost/version.hpp
index 03b33f9ae0..725165f44d 100644
--- a/boost/version.hpp
+++ b/boost/version.hpp
@@ -19,7 +19,7 @@
// BOOST_VERSION / 100 % 1000 is the minor version
// BOOST_VERSION / 100000 is the major version
-#define BOOST_VERSION 106400
+#define BOOST_VERSION 106500
//
// BOOST_LIB_VERSION must be defined to be the same as BOOST_VERSION
@@ -27,6 +27,6 @@
// number, y is the minor version number, and z is the patch level if not 0.
// This is used by <config/auto_link.hpp> to select which library version to link to.
-#define BOOST_LIB_VERSION "1_64"
+#define BOOST_LIB_VERSION "1_65"
#endif
diff --git a/boost/wave/util/cpp_include_paths.hpp b/boost/wave/util/cpp_include_paths.hpp
index d0f2fcbaa8..e5e17c8d03 100644
--- a/boost/wave/util/cpp_include_paths.hpp
+++ b/boost/wave/util/cpp_include_paths.hpp
@@ -15,6 +15,7 @@
#include <list>
#include <utility>
+#include <boost/assert.hpp>
#include <boost/wave/wave_config.hpp>
#include <boost/wave/util/filesystem_compatibility.hpp>
@@ -58,8 +59,7 @@ struct bidirectional_map
typedef std::pair<FromType, ToType> value_type;
#if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS) || \
- (defined(BOOST_MSVC) && \
- ( (BOOST_MSVC < 1300) || (BOOST_MSVC == 1600) )) || \
+ (defined(BOOST_MSVC) && (BOOST_MSVC == 1600) ) || \
(defined(BOOST_INTEL_CXX_VERSION) && \
(defined(_MSC_VER) && (BOOST_INTEL_CXX_VERSION <= 700)))
@@ -442,18 +442,13 @@ void include_paths::set_current_directory(char const *path_)
fs::path filepath (create_path(path_));
fs::path filename = util::complete_path(filepath, current_dir);
- if (fs::exists(filename) && fs::is_directory(filename)) {
- current_rel_dir.clear();
- if (!as_relative_to(filepath, current_dir, current_rel_dir))
- current_rel_dir = filepath;
- current_dir = filename;
- }
- else {
- current_rel_dir.clear();
- if (!as_relative_to(branch_path(filepath), current_dir, current_rel_dir))
- current_rel_dir = branch_path(filepath);
- current_dir = branch_path(filename);
- }
+
+ BOOST_ASSERT(!(fs::exists(filename) && fs::is_directory(filename)));
+
+ current_rel_dir.clear();
+ if (!as_relative_to(branch_path(filepath), current_dir, current_rel_dir))
+ current_rel_dir = branch_path(filepath);
+ current_dir = branch_path(filename);
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/boost/wave/util/cpp_iterator.hpp b/boost/wave/util/cpp_iterator.hpp
index 999d961908..9d61b82f2a 100644
--- a/boost/wave/util/cpp_iterator.hpp
+++ b/boost/wave/util/cpp_iterator.hpp
@@ -607,7 +607,7 @@ pp_iterator_functor<ContextT>::operator()()
break;
}
- if (whitespace.must_insert(id, act_token.get_value())) {
+ if (token_is_valid(act_token) && whitespace.must_insert(id, act_token.get_value())) {
// must insert some whitespace into the output stream to avoid adjacent
// tokens, which would form different (and wrong) tokens
whitespace.shift_tokens(T_SPACE);
diff --git a/boost/wave/util/flex_string.hpp b/boost/wave/util/flex_string.hpp
index 21c7e75fd1..73c604682c 100644
--- a/boost/wave/util/flex_string.hpp
+++ b/boost/wave/util/flex_string.hpp
@@ -1988,7 +1988,7 @@ public:
flex_string& replace(size_type pos, size_type n1, const value_type* s)
{ return replace(pos, n1, s, traits_type::length(s)); }
- // Replaces at most n1 chars of *this, starting with pos, with n2 occurences of c
+ // Replaces at most n1 chars of *this, starting with pos, with n2 occurrences of c
// consolidated with
// Replaces at most n1 chars of *this, starting with pos,
// with at most n2 chars of str.
diff --git a/boost/wave/wave_config.hpp b/boost/wave/wave_config.hpp
index ec712ef16d..bd29a8a89d 100644
--- a/boost/wave/wave_config.hpp
+++ b/boost/wave/wave_config.hpp
@@ -186,7 +186,9 @@
#endif
#if BOOST_WAVE_SUPPORT_THREADING != 0
-#define BOOST_SPIRIT_THREADSAFE 1
+#ifndef BOOST_SPIRIT_THREADSAFE
+#define BOOST_SPIRIT_THREADSAFE
+#endif
#define PHOENIX_THREADSAFE 1
#else
// disable thread support in Boost.Pool
@@ -202,8 +204,7 @@
// VC7 isn't able to compile the flex_string class, fall back to std::string
// CW up to 8.3 chokes as well *sigh*
// Tru64/CXX has linker problems when using flex_string
-#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || \
- BOOST_WORKAROUND(__MWERKS__, < 0x3200) || \
+#if BOOST_WORKAROUND(__MWERKS__, < 0x3200) || \
(defined(__DECCXX) && defined(__alpha)) || \
defined(BOOST_WAVE_STRINGTYPE_USE_STDSTRING)
@@ -228,7 +229,7 @@
// BOOST_WAVE_STRINGTYPE above.
#include <boost/wave/util/flex_string.hpp>
-#endif // BOOST_WORKAROUND(_MSC_VER, <= 1300) et.al.
+#endif // BOOST_WORKAROUND(__MWERKS__, < 0x3200) et.al.
#endif // !defined(BOOST_WAVE_STRINGTYPE)
///////////////////////////////////////////////////////////////////////////////
diff --git a/boost/weak_ptr.hpp b/boost/weak_ptr.hpp
index dd26869055..fa8574beac 100644
--- a/boost/weak_ptr.hpp
+++ b/boost/weak_ptr.hpp
@@ -10,7 +10,7 @@
// 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/weak_ptr.htm for documentation.
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
//
#include <boost/smart_ptr/weak_ptr.hpp>
diff --git a/boost/xpressive/detail/utility/tracking_ptr.hpp b/boost/xpressive/detail/utility/tracking_ptr.hpp
index aa88e74523..4cb32a047a 100644
--- a/boost/xpressive/detail/utility/tracking_ptr.hpp
+++ b/boost/xpressive/detail/utility/tracking_ptr.hpp
@@ -112,8 +112,10 @@ private:
// for use with a filter_iterator to filter a node out of a list of dependencies
template<typename Derived>
struct filter_self
- : std::unary_function<shared_ptr<Derived>, bool>
{
+ typedef shared_ptr<Derived> argument_type;
+ typedef bool result_type;
+
filter_self(enable_reference_tracking<Derived> *self)
: self_(self)
{
diff --git a/boost/xpressive/match_results.hpp b/boost/xpressive/match_results.hpp
index e7923f87de..2eb5c4b232 100644
--- a/boost/xpressive/match_results.hpp
+++ b/boost/xpressive/match_results.hpp
@@ -1354,8 +1354,10 @@ private:
//
template<typename BidiIter>
struct regex_id_filter_predicate
- : std::unary_function<match_results<BidiIter>, bool>
{
+ typedef match_results<BidiIter> argument_type;
+ typedef bool result_type;
+
regex_id_filter_predicate(regex_id_type regex_id)
: regex_id_(regex_id)
{